此代码再次来自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()
答案 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列的时间。