Flask SQL-Alchemy | MySql - Multiple Foreign Keys issues

こ雲淡風輕ζ 提交于 2019-12-22 19:49:43

问题


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. Why? Whats the right way to do this??


回答1:


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).

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.

The SQLAlchemy tutorial also has a section about relationships: 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.


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. 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). 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)



来源:https://stackoverflow.com/questions/33180337/flask-sql-alchemy-mysql-multiple-foreign-keys-issues

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!