问题
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