gpt4 book ai didi

python - 为什么 SQLAlchemy InstrumentedList 的顺序不持久?

转载 作者:搜寻专家 更新时间:2023-10-30 22:30:45 25 4
gpt4 key购买 nike

快速总结:我想在 SQLAlchemy 中有一个有序的地址列表。但是当我提交时,我的列表顺序会改变。为什么会发生这种情况,我该如何改变它?

详细解释:

  1. 我从附加到用户对象的地址列表开始。
  2. 然后我将“地址”列表的第一个元素替换为新地址。
  3. 然后我打印地址列表……到目前为止,顺序符合我的预期。
  4. 最后我 promise 。在我提交之后我做了一个查询但是我的顺序地址列表已更改。

那么这只是我不理解的关于数据库的一般知识吗?还是 SQLAlchemy InstrumentedList 不像实际列表?我以为我可以更改关系中元素的顺序,但我不知道如何做。


from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()
Session = sessionmaker()

class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(12))

addresses = relationship("Address", back_populates="user")

def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (
self.name, self.fullname, self.password)

class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
email_address = Column(String, nullable=False)
user_id = Column(Integer, ForeignKey('users.id'))

user = relationship("User", back_populates="addresses")

def __repr__(self):
return "<Address(email_address='%s')>" % self.email_address


if __name__ == "__main__":
engine = create_engine('sqlite:///:memory:', echo=False)
Session.configure(bind=engine)
Base.metadata.create_all(engine)
session = Session()

user = User(name='ed', fullname='Ed Jones', password='edspassword')
user.addresses = [Address(email_address='jack@google.com'), Address(email_address='j25@yahoo.com')]
session.add(user)
session.commit()

user = session.query(User).filter_by(name='ed').first()

print("Current order of addresses list at start.")
print(user.addresses)
print()

new_primary_address = Address(email_address='primary@google.com')
user.addresses[0] = new_primary_address

print("Current order of addresses list before commit.")
print("But after chaning addresses[0].")
print(user.addresses)
print()

session.commit()

user = session.query(User).filter_by(name='ed').first()

print("Current order of addresses list after commit.")
print(user.addresses)
print()

print("Why is the order of the InstrumentedList not persistent?")
print("Isn't persistent order what makes a list a list?")

最佳答案

它通常是“数据库”。一个InstrumentedList确实像添加了 ORM 检测 Python 端的实际 list 一样,但是当您 commit Session 的默认行为是使 ORM 管理属性的所有数据库加载状态过期,因此必须在下次访问时刷新列表。这意味着 SELECT 如

2017-05-21 13:32:31,124 INFO sqlalchemy.engine.base.Engine SELECT addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id 
FROM addresses
WHERE ? = addresses.user_id

用于获取列表内容。在 SQL 中 the order of a SELECT is unspecified ,如果没有明确选择,那么您可能会或可能不会以与以前相同的顺序获得这些项目。还要注意ORM操作

user.addresses[0] = new_primary_address

转换为将旧地址元组的 user_id 设置为 NULL 并在表中插入一个新元组的 UPDATE,因此即使行是按插入顺序返回。

如果地址顺序对您很重要,您必须选择顺序。使用 order_by 关系的参数:

class User(Base):
...
addresses = relationship("Address", back_populates="user",
order_by="Address.email_address")

将在获取时按电子邮件地址对地址进行排序。 SQLAlchemy 还提供(感谢您深入挖掘)一个用于可变有序关系的辅助集合类:orderinglist ,如果用作排序,这有助于管理更改时的索引/位置。

您似乎希望地址顺序表明哪个是用户的主要地址。一个单独的标志列会更好地工作。

关于python - 为什么 SQLAlchemy InstrumentedList 的顺序不持久?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44093038/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com