【问题标题】:SQLAlchemy equivalent of Django ORM's relationship-spanning filterSQLAlchemy 相当于 Django ORM 的关系跨越过滤器
【发布时间】:2017-04-03 14:38:25
【问题描述】:

这个例子来自Django documentation

给定(Django)数据库模型:

class Blog(models.Model):
    name = models.CharField(max_length=100)

class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()

在 Django 中我可以使用:

Entry.objects.filter(blog__name__exact='Beatles Blog')

获取具有指定名称的博客的所有 Entry 对象。

问题:给定下面的模型定义,等效的 SQLAlchemy 语句是什么?

class Blog(Base):
    __tablename__ = "blog"
    id = Column(Integer, primary_key=True)
    name = Column(Unicode(100))

class Entry(Base):
    __tablename__ = "entry"
    id = Column(Integer, primary_key=True)
    blogid = Column(Integer, ForeignKey(Blog.id))
    headline = Column(Unicode(255))
    body_text = Column(UnicodeText)

    blog = relationship(Blog, backref="entries")

编辑

我相信有两种方法可以做到这一点:

>>> q = session.query
>>> print q(Entry).join(Blog).filter(Blog.name == u"One blog")
SELECT entry.id AS entry_id, entry.blogid AS entry_blogid, entry.headline AS entry_headline, entry.body_text AS entry_body_text 
FROM entry JOIN blog ON blog.id = entry.blogid 
WHERE blog.name = ?

>>> print q(Entry).filter(Entry.blog.has(Blog.name == u"One blog"))
SELECT entry.id AS entry_id, entry.blogid AS entry_blogid, entry.headline AS entry_headline, entry.body_text AS entry_body_text 
FROM entry 
WHERE EXISTS (SELECT 1 
FROM blog 
WHERE blog.id = entry.blogid AND blog.name = ?)

# ... and of course
>>> blog = q(Blog).filter(Blog.name == u"One blog")
>>> q(Entry).filter(Entry.blog == blog)

还有几个问题:

  1. 除了上述方法之外,还有其他方法可以使用 SQLAlchemy 完成此任务吗?
  2. 如果您可以在多对一关系中使用session.query(Entry).filter(Entry.blog.name == u"One blog"),难道没有意义吗?
  3. 在这种情况下,Django 的 ORM 会生成什么 SQL?

【问题讨论】:

  • 我认为session.query(Entry).filter(Entry.blog.name == u"One blog") 有道理....我第一次使用 SQLAlchemy 时尝试使用它。我认为 SQLAlchemy 在这一点上很烂。

标签: python django-models sqlalchemy


【解决方案1】:

我也一直梦想拥有类似 Django 的“魔术连接”。我熟悉 sqlalchemy-django-query它,我发现它对我的任务来说不够强大。

这就是我创建的原因 https://github.com/absent1706/sqlalchemy-mixins#django-like-queries

它的工作方式类似于sqlalchemy-django-query,但具有更多附加功能(here's a comparison)。它也经过了充分的测试和记录。

【讨论】:

    【解决方案2】:

    怎么样:

    session.query(model.Entry).join((model.Blog, model.Entry.blogid==model.Blog.id)).filter(model.Blog.name=='Beatles Blog').all()
    

    【讨论】:

    • 不需要指定连接条件,SA根据外键计算出来。 session.query(Entry).join(Blog).filter(Blog.name == ...) 成功了。
    • 是的,但它不会造成伤害,而且在更复杂的查询中,这样更安全,我个人认为它提高了可读性。
    • @Bogdan:嗯,不是当它让你不得不滚动阅读它时=p
    【解决方案3】:

    聚会已经迟到了,但我偶然发现了这个:
    https://github.com/mitsuhiko/sqlalchemy-django-query/blob/master/sqlalchemy_django_query.py

    这会尝试使用 django 表示法构建查询。

    来自文档:Post.query.filter_by(pub_date__year=2008)

    【讨论】:

      猜你喜欢
      • 2014-12-29
      • 2018-11-18
      • 2022-06-12
      • 1970-01-01
      • 2015-04-30
      • 2019-07-06
      • 1970-01-01
      • 2016-08-17
      相关资源
      最近更新 更多