Python操作數據庫表時常用SQLAlchemy做ORM,把關係數據庫的表結構映射到對象上,並通過relationship做外鍵關聯,方便進一步處理。
假設需要實現某個“一對多”的場景,從“一”這頭需要取出“多”那頭的全部對象,並按某個字段做排序,如何實現呢?
話不多說,show code。
本例使用sqlite3做數據庫,創建Project和User兩張表,兩者是一對多關係。
核心是在User表中通過backref做反向引用時聲明order_by即可。
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, backref, foreign, relationship
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Project(Base):
__tablename__ = "project"
id = Column(Integer, primary_key=True)
name = Column(String(20))
def __repr__(self):
return "<Project(id='%d', name='%s')>" % (self.id, self.name)
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True)
name = Column(String(20))
project_id = Column(Integer)
project = relationship(Project, primaryjoin=foreign(project_id) == Project.id,
backref=backref("users", order_by=id.desc()))
def __repr__(self):
return "<User(id='%d', name='%s', project_id='%d')>" % (self.id, self.name, self.project_id)
# init database and create tables
def init_db():
engine = create_engine('sqlite:///test.db')
smaker = sessionmaker(bind=engine)
session = smaker()
Base.metadata.create_all(engine)
return engine, smaker, session
# prepare data
def init_data(session):
project = Project(name='Project_A')
session.add(project)
session.commit()
user_a = User(name='user_a', project_id=project.id)
user_b = User(name='user_b', project_id=project.id)
session.add_all([user_a, user_b])
session.commit()
def main():
engine, smaker, session = init_db()
init_data(session)
# test
projects = session.query(Project).all()
for p in projects:
print(p.users)
if __name__ == '__main__':
main()
結果如圖,可以看到User對象是按照id倒序排列。
參考: