问题
With this simplified model:
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
# other attributes
#user many-to-many size associations (using link tables)
sz_shirt_dress_sleeve = db.relationship(
'SizeKeyShirtDressSleeve',
secondary=LinkUserSizeShirtDressSleeve,
backref=db.backref('users', lazy='dynamic'))
strange = {'whyisthisdifferent': db.relationship(
'SizeKeyShirtDressNeck',
secondary=LinkUserSizeShirtDressNeck,
backref=db.backref('users', lazy='dynamic'))}
I would assume that I can use both of these to access the relationship, but it isn't so. See this interactive session:
>>> from app import db
>>> from app.models import User
>>> u1 = User.query.first()
>>> u1
<User id: 1, email: 'admin@admin.com', password_hash: 'pbkdf2:sha256:50000$n2qsqVfu$8d1bc6b0a472818175c21c1a31031ece58e78feca9c6d15a326b28bd7fd80e67'>
>>> u1.strange['whyisthisdifferent']
<RelationshipProperty at 0x106c6d248; no key>
>>> u1.sz_shirt_dress_sleeve
[Dress shirt sleeve size: 3000]
Why does accessing by u1.sz_shirt_dress_sleeve
actually return the result of the query when u1.strange['whyisthisdifferent']
returns the relationship signature? This reminds me of the Javascript difference between returning a function definition or a function literal, but this isn't Javascript.
I do believe that reading the SQLAlchemy Association Proxy documentation will actually get me what I want, but I would still like to understand this behavior.
回答1:
SQLAlchemy uses metaclasses to construct models, which allows it to do all sorts of magic. When you declare the User class, it looks for attributes at the top level which are columns, relationships etc. and changes them to something different. You can check and find that isinstance(User.id, db.Column)
is false. But it doesn't pick up these objects inside something else like a dictionary.
来源:https://stackoverflow.com/questions/50276826/when-accessed-similarly-why-does-a-sqlalchemy-relationship-return-differently