使用声明性语法,如何定义表示多对一集合中最新对象的关系?

时间:2011-09-22 21:25:48

标签: python sqlalchemy

我正在使用SQLAlchemy的声明性语法,我想指定一个提供集合中最新(max primary id)元素的关系。我发现这篇文章:How do I define a SQLAlchemy relation representing the latest object in a collection?但是我很难使用这种模式,只使用Declarative创建一个子查询。任何指针或帮助将不胜感激!

一般理念:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base(bind=engine, metadata=metadata)

from sqlalchemy import *
from sqlalchemy.orm import *

class NewsPaper(Base):
    __tablename__ = "newspapers"
    id = Column(Integer, nullable=False, primary_key=True)
    name = Column(String(255))
    latest_article = relationship("Article",
                                primaryjoin="(Article.newspaper_id==NewsPaper.id) &"
                                               "(Article.id==SUBQUERY_FOR_LATEST_ID)")
    def __repr__(self):
        return '''<name={0}>'''.format(self.name)


class Article(Base):
    __tablename__ = "articles"
    id = Column(Integer, nullable=False, primary_key=True)
    title = Column(String(255))
    newspaper_id =  Column(Integer, ForeignKey('newspapers.id'))
    newspaper = relationship("NewsPaper", backref=backref('articles') )

    def __repr__(self):
        return '''<title={0}>'''.format(self.title)

1 个答案:

答案 0 :(得分:2)

最简单的方法是,一旦定义了所有类,定义类之外的关系 从latest_article中删除NewsPaper的定义,并在class Article定义后添加以下代码(直接取自您链接到的Mike的答案):

# define the relationship
t_article = Article.__table__
t_newpaper = NewsPaper.__table__
latest_c = (select([t_article.c.id]).
            where(t_article.c.newspaper_id == t_newpaper.c.id).
            order_by(t_article.c.id.desc()).
            limit(1).
            correlate(t_newpaper).
            as_scalar()
            )
NewsPaper.latest_article = relationship("Article", 
                            primaryjoin=and_(
                                t_article.c.id==latest_c,
                                t_article.c.newspaper_id==t_newpaper.c.id,
                            ),
                            uselist=False
                           )

但需要注意的是:关系直接在数据库上运行,因此它不会包含那些尚未提交但属于会话的Article个实例。而且很可能他们会是你真正想要的。所以要小心。