flask_sqlalchemy:为什么由Model.query.filter_by()创建的实例.first()不在模型中运行__init __()

时间:2017-06-28 20:02:16

标签: python flask-sqlalchemy

我有一个像这样的用户模型:

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key = True)
    username = db.Column(db.String(64), unique=True, index=True
    # ...

    def __init__(self, **kwargs):
        pass

当实例创建如:user = User(username='john')时,构造函数被成功调用。

但如果实例由user = User.query.filter_by(username=john).first()返回,则无论如何都不会调用构造函数。

我已经检查过查询返回的实例是User的实例,因此在查询完成时应该调用构造函数。因为据我所知,每次创建实例时都会调用构造函数。

问题是:为什么会发生这种情况以及在查询返回用户时如何调用__init__

1 个答案:

答案 0 :(得分:2)

我只是遇到了同样的问题(构造函数未被调用),并且通过SQLAlchemy documentation阅读,这正是它应该如何表现的。从Query对象创建实例时,它不会调用__init__方法。相反,它调用标记为reconstructor(装饰器)的方法。

要将方法标记为重建器,请声明无参数方法并使用SQLAlchemy实例中的方法对其进行修饰:

class User(UserMixin, db.Model):

    @db.reconstructor
    def reload(self):
        # Will be run when loading from a Query object

来自文档:

  

任何方法都可能被标记为reconstructor(),甚至是__init__方法。 SQLAlchemy将调用没有参数的reconstructor方法。

因此,如果您的班级有初始化代码,或者您致电super(),则可以从__init__调用您的重建器:

class User(UserMixin, db.Model):

    def __init__(self, **kwargs):
        super(User, self).__init__(**kwargs)
        self.reload()

    @db.reconstructor
    def reload(self):
        # Process data from model

这样,reload()会在查询时调用自定义初始化