【问题标题】:Defining a constructor for ponyorm's Entities results in TypeError为 ponyorm 的实体定义构造函数会导致 TypeError
【发布时间】:2015-08-27 22:17:24
【问题描述】:

我只是想尝试一下用于小型个人 Web 应用程序的小马 orm 映射器。 除了为实体定义自定义构造函数之外,一切正常。

在下面的代码中,我创建了一个带有字符串字段 name 的简单实体,并定义了一个构造函数,它除了将参数重定向到父构造函数之外什么都不做(在我的真实应用程序中,我更改了一些参数,然后将它们传递给父构造函数)。之后我创建一个User 并打印它的名字。

from pony.orm import Database, Required, db_session, commit


db = Database("sqlite", ":memory:", create_db=True)


class User(db.Entity):
    def __init__(self, *args, **kwargs):
        super(User, self).__init__(*args, **kwargs)

    name = Required(str)


db.generate_mapping(create_tables=True)

with db_session:
    u = User(name="Admin")
    commit()
    print(u, u.name)

错误消息是TypeError: object.__init__() takes no parameters,与super()call 位于同一行。 看起来关键字参数被发送到object 而不是db.Entity。 当我删除构造函数时,一切正常

那么为什么它不起作用。像我的示例中的构造函数不应该总是工作(当然什么也不做)吗? ponyorm 中有什么东西阻止它工作还是我在这里遗漏了什么?

为了完整起见,我的实体定义实际上看起来像这样

class User(db.Entity):
    def __init__(self, *args, **kwargs):
        if "password" not in kwargs:
            raise ValueError("password is required")
        kwargs["password"] = werkzeug.security.generate_password_hash(kwargs["password"])
        super().__init__(*args, **kwargs)

    name = Required(str)
    password = Required(str)

它产生相同的结果。

在官方文档中还说至少允许在实体中创建方法。 http://doc.ponyorm.com/entities.html#adding-custom-methods-to-entities 。 但它并没有说明构造函数。

【问题讨论】:

    标签: python python-3.x ponyorm


    【解决方案1】:

    直到那一刻,Entity 类根本没有 __init__ 方法。由于历史原因,实体实例的初始化发生在__new__ 方法中。因此,当您调用super(User, self).__init__ 时,您实际上调用了object.__init__ 方法。虽然在 Python 2 中 object.__init__ 方法静默接受任何参数,但在 Python 3 中,当您将任何参数传递给该方法时,该方法会引发错误(您遇到的错误)。

    查看您的问题后,我们更改了实体实例的初始化逻辑,现在我们以传统方式使用__init__ 方法。如果您从 GitHub 获取 PonyORM 的最新版本,您的代码应该可以正常工作。此更改将成为下一版本 PonyORM 0.6.2 的一部分。

    感谢您指出这一点!

    【讨论】:

    • 太棒了。现在错误消息对我来说实际上是有意义的。在__new__ 方法中进行初始化是否有任何原因(除了“历史”之外)?
    • 在内存中创建实体实例有两种情况:一种是用户新建实例时,另一种是从数据库中加载对象时。 Pony 对其对象使用 IdentityMap 模式。这样 Pony 可以防止重复:如果一个对象已经被加载,那么第二次尝试加载同一个对象不会创建一个重复的对象,而只是返回前一个。 __new__ 方法允许控制对象实例化过程并返回先前存在的对象而不是创建新对象。现在 Pony 也可以不定义__new__
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    • 1970-01-01
    相关资源
    最近更新 更多