简体   繁体   English

烧瓶SQL炼金术 MySql-多个外键问题

[英]Flask SQL-Alchemy | MySql - Multiple Foreign Keys issues

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)


class Devices(db.Model):
    __tablename__ = 'devices'
    id = db.Column(db.Integer, primary_key=True)
    purpose = db.Column('purpose', db.String(64))
    type = db.Column('type', db.String(64))
    name = db.Column('name', db.String(64))
    channel = db.Column('channel', db.Integer)
    role_id = db.Column('role_id', db.Integer)
    role_permissions = db.Column('role_permissions', db.Integer)
    role = db.ForeignKeyConstraint(['role_id', 'role_permissions'], ['roles.id', 'roles.permissions'])

Then I would expect this to work: 然后,我希望这可以工作:

dev = Devices(purpose="lights",type="tcp",name="zeus",channel=8)
role = Role.query.first()
dev.role = role
db.session.add(dev)
db.session.commit()

But once persisted, role_id and role_permissions get null value. 但是,一旦持久化,role_id和role_permissions将获得空值。 Why? 为什么? Whats the right way to do this?? 什么是正确的方法?

You need to define a relationship in addition to the foreign key. 除了外键之外,您还需要定义一个关系。

A foreign key is just a database-level constraint to ensure you cannot reference rows that don't exist (additionally, it helps SQLAlchemy setup a relationship without you specifying another time how the two tables are linked). 外键只是数据库级别的约束,可以确保您不能引用不存在的行(此外,它可以帮助SQLAlchemy建立关系,而无需您指定其他时间如何链接两个表)。

You want this in your model: 您需要在模型中这样做:

class Devices(db.Model):
    __table_args__ = (db.ForeignKeyConstraint(['role_id', 'role_permissions'], ['roles.id', 'roles.permissions']),)
    # ...
    role = db.relationship('Role', backref=db.backref('devices'))

By doing so, device.role = some_role will properly populate the foreign keys, and in addition each Role instance will have a devices collection that gives you access to its associated devices. 这样, device.role = some_role将正确填充外键,此外,每个Role实例将具有一个devices集合,该集合可让您访问与其关联的设备。

The SQLAlchemy tutorial also has a section about relationships: http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#building-a-relationship SQLAlchemy教程还提供了有关关系的部分: http : //docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#building-a-relationship

You can pretty much follow it; 您几乎可以遵循它; Flask-SQLAlchemy and plain SQLalchemy don't really differ - Flask-SQLAlchemy simply makes many things accessible via the db object to avoid importing them explicitly. Flask-SQLAlchemy和普通的SQLalchemy并没有真正的不同-Flask-SQLAlchemy只是通过db对象使许多东西可以访问,以避免显式导入它们。


By the way, since Role.id is the primary key, you don't need to include role_permissions in the foreign key - you cannot have more than one role the same ID since the primary key is always unique. 顺便说一句,由于Role.id是主键,所以您不需要在外键中包含role_permissions您不能同时拥有多个具有相同ID的角色,因为主键始终是唯一的。 This makes your model even easier: 这使您的模型更加容易:

class Devices(db.Model):
    # ...
    role_id = db.Column('role_id', db.Integer, db.ForeignKey('roles.id'))
    role = db.relationship('Role', backref=db.backref('devices'))

You can also get rid of the role_permissions column in your Devices model (which, by the way, should be named Device ). 您还可以摆脱Devices模型中的role_permissions列(顺便说一下,应将其命名为Device )。 If you need the permissions, simply get it from the role (if you usually need it, add lazy=False to the foreign key, then querying a device will always join the role table to avoid extra queries) 如果需要权限,只需从角色中获取权限即可(如果通常需要,将lazy=False添加到外键中,然后查询设备将始终加入角色表,以避免额外的查询)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM