Python SQLalchemy类可以同时具有一对多和一对一的关系吗?
我试图将歌曲和收视率之间的一对一关系添加到我的flask模型中,但在运行查询时出错。我已经遵循了中的步骤,但当涉及到sqlalchemy时,我仍然感到迷失。歌曲已经有了一对多的关系,也许它不能同时有一对多和一对一的关系Python SQLalchemy类可以同时具有一对多和一对一的关系吗?,python,sqlalchemy,flask-sqlalchemy,Python,Sqlalchemy,Flask Sqlalchemy,我试图将歌曲和收视率之间的一对一关系添加到我的flask模型中,但在运行查询时出错。我已经遵循了中的步骤,但当涉及到sqlalchemy时,我仍然感到迷失。歌曲已经有了一对多的关系,也许它不能同时有一对多和一对一的关系 from application import db association_table = db.Table('association', db.Column('songs_id', db.Integer,
from application import db
association_table = db.Table('association',
db.Column('songs_id', db.Integer,
db.ForeignKey('songs.id')),
db.Column('genres_id', db.Integer,
db.ForeignKey('genres.id'))
)
class Rating(db.Model):
__tablename__ = 'songs_ratings'
id = db.Column(db.Integer, primary_key=True)
rating = db.Column(db.Numeric(precision=3, scale=2),
index=True, nullable=False)
song_id = db.Column(db.Integer, db.ForeignKey('songs.id'))
song = db.relationship("Song", uselist=False,
back_populates="songs_ratings")
def __repr__(self):
return '{}'.format(self.rating)
class Song(db.Model):
__tablename__ = 'songs'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80), index=True, unique=True, nullable=False)
artist = db.Column(db.String(30), primary_key=False,
unique=False, nullable=False)
added = db.Column(db.Date, nullable=False)
rating = db.relationship("Rating", back_populates="songs")
genres = db.relationship(
"Genre", secondary=association_table, backref=db.backref('songs'))
def __repr__(self):
return '{};{};{}'.format(self.title, self.artist, self.added)
class Genre(db.Model):
__tablename__ = 'genres'
id = db.Column(db.Integer, primary_key=True)
category = db.Column(db.String(80), index=True,
unique=True, nullable=False)
def __repr__(self):
return '{}'.format(self.category)
错误
运行代码时出现的错误
---------------------------------------------------------------------------
InvalidRequestError Traceback (most recent call last)
<ipython-input-7-99ffacdf2d91> in <module>
----> 1 query = db.session.query(Rating, Song).filter(Rating.id==Song.id)
2 df = pd.read_sql_query(query, db.engine)
3 df
<string> in query(self, *entities, **kwargs)
~\AppData\Local\Programs\Python\Python37\lib\site-packages\sqlalchemy\orm\session.py in query(self, *entities, **kwargs)
2066 """
2067
-> 2068 return self._query_cls(entities, self, **kwargs)
2069
2070 def _identity_lookup(
~\AppData\Local\Programs\Python\Python37\lib\site-packages\sqlalchemy\orm\query.py in __init__(self, entities, session)
173
174 self.session = session
--> 175 self._set_entities(entities)
176
177 def _set_propagate_attrs(self, values):
~\AppData\Local\Programs\Python\Python37\lib\site-packages\sqlalchemy\orm\query.py in _set_entities(self, entities)
187 post_inspect=True,
188 )
--> 189 for ent in util.to_list(entities)
190 ]
191
~\AppData\Local\Programs\Python\Python37\lib\site-packages\sqlalchemy\orm\query.py in <listcomp>(.0)
187 post_inspect=True,
188 )
--> 189 for ent in util.to_list(entities)
190 ]
191
~\AppData\Local\Programs\Python\Python37\lib\site-packages\sqlalchemy\sql\coercions.py in expect(role, element, apply_propagate_attrs, argname, post_inspect, **kw)
166 if insp is not None:
167 if post_inspect:
--> 168 insp._post_inspect
169 try:
170 resolved = insp.__clause_element__()
~\AppData\Local\Programs\Python\Python37\lib\site-packages\sqlalchemy\util\langhelpers.py in __get__(self, obj, cls)
1158 if obj is None:
1159 return self
-> 1160 obj.__dict__[self.__name__] = result = self.fget(obj)
1161 obj._memoized_keys |= {self.__name__}
1162 return result
~\AppData\Local\Programs\Python\Python37\lib\site-packages\sqlalchemy\orm\mapper.py in _post_inspect(self)
2095
2096 """
-> 2097 self._check_configure()
2098
2099 @HasMemoized.memoized_attribute
~\AppData\Local\Programs\Python\Python37\lib\site-packages\sqlalchemy\orm\mapper.py in _check_configure(self)
1872 def _check_configure(self):
1873 if self.registry._new_mappers:
-> 1874 _configure_registries({self.registry}, cascade=True)
1875
1876 def _post_configure_properties(self):
~\AppData\Local\Programs\Python\Python37\lib\site-packages\sqlalchemy\orm\mapper.py in _configure_registries(registries, cascade)
3382 # the order of mapper compilation
3383
-> 3384 _do_configure_registries(registries, cascade)
3385 finally:
3386 _already_compiling = False
~\AppData\Local\Programs\Python\Python37\lib\site-packages\sqlalchemy\orm\mapper.py in _do_configure_registries(registries, cascade)
3417 )
3418 e._configure_failed = mapper._configure_failed
-> 3419 raise e
3420
3421 if not mapper.configured:
InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'mapped class Rating->songs_ratings'. Original exception was: Mapper 'mapped class Song->songs' has no property 'songs_ratings'
---------------------------------------------------------------------------
InvalidRequestError回溯(最近一次呼叫上次)
在里面
---->1 query=db.session.query(Rating,Song.filter)(Rating.id==Song.id)
2 df=pd.read\u sql\u查询(查询,db.engine)
3 df
在查询中(自我、*实体、**kwargs)
查询中的~\AppData\Local\Programs\Python\Python37\lib\site packages\sqlalchemy\orm\session.py(self,*entities,**kwargs)
2066 """
2067
->2068返回self.\u查询\u cls(实体、self、**kwargs)
2069
2070定义标识查找(
~\AppData\Local\Programs\Python\Python37\lib\site packages\sqlalchemy\orm\query.py in\uuuuuu init\uuuu(self,entities,session)
173
174 self.session=会话
-->175自组实体(实体)
176
177定义集传播属性(自身、值):
~AppData\Local\Programs\Python\Python37\lib\site packages\sqlalchemy\orm\query.py in\u set\u entities(self,entities)
187事后检查=正确,
188 )
-->189用于使用对象列表中的ent(实体)
190 ]
191
(.0)中的~\AppData\Local\Programs\Python\Python37\lib\site packages\sqlalchemy\orm\query.py
187事后检查=正确,
188 )
-->189用于使用对象列表中的ent(实体)
190 ]
191
expect中的~\AppData\Local\Programs\Python\Python37\lib\site packages\sqlalchemy\sql\impressions.py(角色、元素、应用传播属性、argname、后期检查、**kw)
166如果insp不是无:
167如果进行后检查:
-->168督察
169尝试:
170已解决=检验条款元素()
获取(self,obj,cls)中的~\AppData\Local\Programs\Python\Python37\lib\site packages\sqlalchemy\util\langhelpers.py
1158如果obj为无:
1159回归自我
->1160 obj.\uuuuu dict\uuuuu[self.\uuuuuuuu name\uuuuuuuu]=结果=self.fget(obj)
1161 obj._memonized_keys |={self.uu name_uuuu}
1162返回结果
~\AppData\Local\Programs\Python\Python37\lib\site packages\sqlalchemy\orm\mapper.py in\u post\u inspect(self)
2095
2096 """
->2097自我检查配置()
2098
2099@hasmomeized.memomeized_属性
~\AppData\Local\Programs\Python\Python37\lib\site packages\sqlalchemy\orm\mapper.py in\u check\u configure(self)
1872 def检查配置(自):
1873如果自注册。新映射程序:
->1874_配置_注册表({self.registry},cascade=True)
1875
1876定义后配置属性(自):
\u configure\u注册表中的~\AppData\Local\Programs\Python\Python37\lib\site packages\sqlalchemy\orm\mapper.py(注册表,级联)
3382#地图编纂的顺序
3383
->3384\u do\u configure\u注册表(注册表,级联)
3385最后:
3386 _已_编译=False
\u do\u configure\u注册表中的~\AppData\Local\Programs\Python\Python37\lib\site packages\sqlalchemy\orm\mapper.py(注册表,级联)
3417 )
3418 e._configure_failed=映射器。_configure_failed
->3419上升e
3420
3421如果未配置mapper.configured:
InvalidRequestError:一个或多个映射程序未能初始化-无法继续初始化其他映射程序。触发映射器:“映射类分级->歌曲分级”。最初的例外是:映射器“映射类歌曲->歌曲”没有“歌曲”属性
该代码几乎没有问题:
后填充的匹配。你有:
/歌曲
在一个关系中,以及歌曲评级
/评级
在另一个规范中歌曲
class Rating(db.Model):
# ...
song_id = db.Column(db.Integer, db.ForeignKey("songs.id"))
song = db.relationship("Song", back_populates="rating")
class Song(db.Model):
# ...
rating = db.relationship("Rating", uselist=False, back_populates="song")
uselist=False
,而不是在第一个关系上使用uselist=False(虽然它不会造成真正的伤害),因为外键是从Rating
到Song
但是,考虑到它是1对1关系,并且没有歌曲就不能存在评级,您可以实际重用您的原始模型,并在
Rating.id
列上指定ForeignKey
关系,方法是更改Rating
模型,如下所示:
class Rating(db.Model):
__tablename__ = "songs_ratings"
id = db.Column(db.Integer, db.ForeignKey("songs.id"), primary_key=True) # <- added FK
rating = db.Column(db.Numeric(precision=3, scale=2), index=True, nullable=False)
song = db.relationship("Song", back_populates="rating")
等级评定(db.Model):
__tablename_u=“歌曲\u评级”
id=db.Column(db.Integer,db.ForeignKey(“songs.id”),primary_key=True)#这解决了我所有的问题。谢谢!