Flask-SQLAlchemy构造函数混淆

时间:2014-07-28 23:19:57

标签: python python-2.7 flask sqlalchemy flask-sqlalchemy

此代码再次来自Miguel Grindberg的书" Flask Web Development"。在models.py中,我们有3个类,一个Role类,它有3个角色(User,Moderator,Administrator),User类(id,username,email,role_id,password_hash,确认)和Permsission类(下面的代码)。在第9页的第9页中,他向User类添加了一些代码,以检查电子邮件地址是否属于管理员,如果是,则将其添加到角色中。如果不是,则将用户添加到默认角色(用户)。 。

def __init__(self, **kwargs):
    super(User, self).__init__(**kwargs)
    if self.role is None:
        if self.email == current_app.config['FLASKY_ADMIN']:
            self.role = Role.query.filter_by(permissions=0xff).first()
    if self.role is None:
        self.role = Role.query.filter_by(default=True).first()

我的问题是,为什么我们需要这个代码的构造函数?构造函数不能在文件的任何其他部分使用(下面的完整代码),那么为什么我们现在需要一个呢?我已经在Stack(Flask-SQLAlchemy Constructor)上查看了这个问题,它就基础类构造函数提供了一些关于这个主题的知识,但不是为什么我需要一个构造函数来完成这段代码。 。再次感谢任何帮助。

class Permission:
    FOLLOW = 0x01
    COMMENT = 0x02
    WRITE_ARTICLES = 0x04
    MODERATE_COMMENTS = 0x08
    ADMINISTER = 0x80


class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    default = db.Column(db.Boolean, default=False, index=True)
    permissions = db.Column(db.Integer)
    users = db.relationship('User', backref='role', lazy='dynamic')

@staticmethod
def insert_roles():
    roles = {
        'User': (Permission.FOLLOW |
                 Permission.COMMENT |
                 Permission.WRITE_ARTICLES, True),
        'Moderator': (Permission.FOLLOW |
                      Permission.COMMENT |
                      Permission.WRITE_ARTICLES |
                      Permission.MODERATE_COMMENTS, False),
        'Administrator': (0xff, False)
    }
    for r in roles:
        role = Role.query.filter_by(name=r).first()
        if role is None:
            role = Role(name=r)
        role.permissions = roles[r][0]
        role.default = roles[r][1]
        db.session.add(role)
    db.session.commit()

def __repr__(self):
    return '<Role %r>' % self.name


class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(64), unique=True, index=True)
    username = db.Column(db.String(64), unique=True, index=True)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
    password_hash = db.Column(db.String(128))
    confirmed = db.Column(db.Boolean, default=False)

    def __init__(self, **kwargs):
        super(User, self).__init__(**kwargs)
        if self.role is None:
            if self.email == current_app.config['FLASKY_ADMIN']:
                self.role = Role.query.filter_by(permissions=0xff).first()
            if self.role is None:
                self.role = Role.query.filter_by(default=True).first()

3 个答案:

答案 0 :(得分:0)

在典型的OO术语中,Python中更接近的“构造函数”是__new__方法,而不是__init__。虽然坦率地说它并没有很好地映射到Python概念:你有__new__方法来创建对象,而__init__通常用于初始化。那么也许这是一个“拆分”构造函数?

无论如何,.__init__是Python中我们通常调整实例属性的地方,因此上面的super()方法会对User超类进行初始化,而子类的__init__的其余部分会进行初始化孩子班。你必须做一些事情,比如说实现某些依赖于关键字属性的逻辑等等 - 你要么在类之外做(这违反了封装原则),要么在类或实例中的某个方法中执行。 __init__是典型的,我很惊讶为什么有人不会使用它。

您还列出了一些SQLAlchemy对象,其中包含不使用__tablename__的声明性__init__类属性。好吧,zzzeek是一个黑魔法师做着邪恶和道德上有争议的东西,所以他已经超越了我们凡人每天使用的peon __init__方法。 ; - )

答案 1 :(得分:0)

def __init__(self, **kwargs):
super(User, self).__init__(**kwargs)
if self.role is None:
    if self.email == current_app.config['FLASKY_ADMIN']:
        self.role = Role.query.filter_by(permissions=0xff).first()
if self.role is None:
    self.role = Role.query.filter_by(default=True).first()

我认为有某种预处理,超级类别用于ealrier检查。因此,每当我们查询用户时,都会进行此项检查。

答案 2 :(得分:0)

无论何时创建新的User实例,构造函数都会为该User实例分配一个角色。如果未创建此构造函数,则每次创建User实例时,都必须在其他地方(例如,在路由中)为其分配角色。但这假设仅当提交表单和/或调用路由时,才会在您的应用程序内创建User实例。这可能很杂乱,并且使某些用户具有“无”角色,如果您的应用程序不期望该角色,则可能会让用户在他们不允许执行的网站上执行操作。

默认情况下,Flask-SQLAlchemy使用SQLAlchemy的基类定义构造函数(每个Flask-SQLAlchemy Constructor)。这就是为什么无需创建构造函数即可在Flask-SQLAlchemy中创建模型的原因,因为它是默认创建的。

因此,如果您想在创建模型实例时做一些特定的事情(例如基于某种逻辑为列分配值),则需要自己创建构造函数,但可以使用super(MODEL, self).__init__(**kwargs)由于super继承了基类,因此节省了键入该模型中N列的时间。