【问题标题】:Flask SQL-Alchemy | MySql - Multiple Foreign Keys issues烧瓶 SQLAlchemy | MySql - 多个外键问题
【发布时间】:2016-01-15 18:55:27
【问题描述】:
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'])

那么我希望这会起作用:

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

但是一旦持久化,role_id 和 role_permissions 就会得到空值。为什么?这样做的正确方法是什么??

【问题讨论】:

    标签: python sqlalchemy flask-sqlalchemy


    【解决方案1】:

    除了外键之外,你还需要定义一个关系。

    外键只是一个数据库级别的约束,以确保您不能引用不存在的行(此外,它有助于 SQLAlchemy 建立关系,而无需您指定另一个时间如何链接两个表)。

    你想在你的模型中加入这个:

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

    通过这样做,device.role = some_role 将正确填充外键,此外,每个角色实例将具有一个 devices 集合,可让您访问其关联的设备。

    SQLAlchemy 教程还有一个关于关系的部分: http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#building-a-relationship

    你几乎可以跟随它; Flask-SQLAlchemy 和普通的 SQLalchemy 并没有真正的区别 - Flask-SQLAlchemy 只是让许多东西通过 db 对象访问,以避免显式导入它们。


    顺便说一下,由于Role.id 是主键,因此您不需要在外键中包含role_permissions - 由于主键始终是唯一的,因此同一ID 不能有多个角色。这使您的模型更加容易:

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

    您还可以删除 Devices 模型中的 role_permissions 列(顺便说一下,它应该命名为 Device)。如果需要权限,直接从角色中获取即可(如果平时需要,在外键中添加lazy=False,然后查询设备会一直加入角色表,避免额外查询)

    【讨论】:

    • 我已经为此苦苦挣扎了很长时间。感激不尽
    • 我这样做是因为我的应用程序使用 Flask-REST,因此更容易在单个 json 对象中拥有我需要的所有数据。我还在使用 UserDevices 模型在用户和设备之间建立多对多关系,并且被困在做几乎相同的事情。所以我可能很快就会遇到其他问题。大声笑非常感谢你
    • 你不能告诉flask-rest从device.role.permissions而不是device.role_permissions获取它吗?无论如何,返回 self.role.permissions 的简单属性也可以完成这项工作
    猜你喜欢
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 2020-02-19
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 2012-12-29
    相关资源
    最近更新 更多