SQLAlchemy动态&定制的集合类

时间:2016-02-22 06:10:33

标签: python sqlalchemy

我有以下SQLAlchemy模型:

from datetime import date

from app import Base
from sqlalchemy import Column, Integer, String, ForeignKey, Date
from sqlalchemy.orm import relationship

class Article(Base):

    __tablename__ = 'article'

    id = Column(Integer, primary_key=True)
    title = Column(String)

    posts = relationship('Post', back_populates='article')


class Post(Base):

    __tablename__ = 'post'

    id = Column(Integer, primary_key=True)
    article_id = Column(Integer, ForeignKey('article.id'))
    date = Column(Date)

    article = relationship('Article', back_populates='posts')

我希望能够快速灵活地将文章article的帖子从日期start_date和日期end_date之间发布。

我知道我能做到:

`session.query(Post).filter(Post.article == article, Post.date >= start_date, Post.date < end_date).all()`

但是我觉得它太长了而且不够“面向对象”。

经过一些研究,我发现我可以使用lazy的{​​{1}}参数:

relationship

之后,“posts”属性不再是一个列表,而是一个Query Object,它允许我们这样做:

posts = relationship('Post', back_populates='article', lazy='dynamic')

但我想做的是:

article.posts.filter(Post.date >= start_date, Post.date < end_date).all()

我想我必须使用article.posts[start_date:end_date] 属性,例如:

collection_class

但我不知道在class DatedList(list): def __getitem__(self, item): if isinstance(item, slice): # What to do here ? else: super(DatedList, self).__getitem__(item) posts = relationship('Post', back_populates='article', lazy='dynamic', collection_class=DatedList) 函数内写什么,因为我们无法访问__getitem__对象给出的查询!

有人有想法可以帮助我吗?

1 个答案:

答案 0 :(得分:3)

我通过发布在SQLAlchemy Google Group上找到了解决方案。

正如Mike Baker所说,collection_class不能使用lazy设置的dynamic参数,所以我不得不使用query_class参数:

from sqlalchemy.orm import Query


class PostClassQuery(Query):

    def __getitem__(self, item):

        if isinstance(item, slice) and (isinstance(item.start, date) or isinstance(item.stop, date)):
            query = self
            if isinstance(item.start, date):
                query = query.filter(Post.date >= item.start)
            if isinstance(item.stop, date):
                query = query.filter(Post.date < item.stop)
            return query.all()
        else:
            super(PostClassQuery, self).__getitem__(item)

在文章实体之后:

posts = relationship('Post', back_populates='article', lazy='dynamic', query_class=PostClassQuery)

如果您愿意,您甚至可以通过移除.all()中的return.query.all()来返回查询而不是结果,这样您就可以执行article.posts[date(2015, 1, 1):date(2015, 6, 1)][10:20]之类的操作。