首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >SQLAlchemy能做什么和Django ORM不能做什么的示例

SQLAlchemy能做什么和Django ORM不能做什么的示例
EN

Stack Overflow用户
提问于 2013-08-13 08:58:32
回答 2查看 21.3K关注 0票数 86

我最近做了很多研究,对比在SQLAlchemy中使用金字塔和在Django中保留当前的应用程序。这本身就是一场完整的辩论,但我不在这里讨论这个。

我想知道的是,为什么人们普遍认为SQLAlchemy比Django ORM更好?几乎所有的比较,如果不是所有的比较,我发现在这两个有利于SQLAlchemy。我认为性能是一个很重要的因素,因为SQLAlchemy的结构让它可以更顺利地转换为SQL。

但是,我也听说对于更难的任务,Django ORM几乎不可能使用。我想了解一下这个问题会有多大。我一直在读到切换到SQLAlchemy的原因之一是Django ORM不再满足您的需求。

所以,简而言之,有人能提供一个查询(不一定是实际的SQL语法),SQLAlchemy可以做到,但Django ORM不可能不添加额外的原始SQL就做到吗?

更新

自从我第一次问起,我就注意到这个问题得到了相当多的关注,所以我想多加两分钱。

最后,我们最终使用了SQLAlchemy,我必须说我对这个决定很满意。

我重新讨论这个问题是为了提供SQLAlchemy的一个附加特性,到目前为止,我还无法在Django ORM中复制该特性。如果有人能提供一个如何做到这一点的例子,我将很乐意收回我的话。

假设你想使用一些postgresql函数,比如some (),它提供一个模糊的比较(参见:Finding similar strings with PostgreSQL quickly - tl;dr输入两个字符串得到一个百分比的相似度)。

我对如何使用Django ORM做了一些搜索,除了使用原始sql之外什么也没有找到,从他们的文档中可以明显看出:https://docs.djangoproject.com/en/dev/topics/db/sql/

Model.objects.raw('SELECT * FROM app_model ORDER BY \
similarity(name, %s) DESC;', [input_name])

然而,SQLalchemy有http://docs.sqlalchemy.org/en/latest/core/sqlelement.html#sqlalchemy.sql.expression.func (),如下所示:

from sqlalchemy import desc, func
session.query(Model).order_by(func.similarity(Model.name, input_name))

这允许您为任何已定义的sql/postgresql/etc函数生成sql,而不需要原始sql。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-13 18:43:55

这几乎是非建设性的,但我还是要咬一口。

假设我们需要为多个不同的帐户维护某些项目的库存。DDL如下:

CREATE TABLE account (
    id serial PRIMARY KEY,
    ...
);

CREATE TABLE item (
    id serial PRIMARY KEY,
    name text NOT NULL,
    ...
);

CREATE TABLE inventory (
    account_id integer NOT NULL REFERENCES account(id),
    item_id integer NOT NULL REFERENCES item(id),
    amount integer NOT NULL DEFAULT 0 CHECK (amount >= 0),
    PRIMARY KEY (account_id, item_id)
);

首先,Django ORM不能使用复合主键。是的,您总是可以添加一个代理键和唯一约束,但这比您实际需要的多了一列和一个索引。对于列数很少的大表,这会增加显着的大小和性能开销。此外,ORM通常在使用主键以外的任何其他标识映射时都会遇到问题。

现在,假设我们想要查询给定帐户的库存中的每个项目及其数量,但也包括数量设置为0的所有不存在的项目。然后按数量降序排序。对应的SQL:

SELECT item.id, item.name, ..., coalesce(inventory.amount, 0) AS amount
    FROM item LEFT OUTER JOIN inventory
        ON item.id = inventory.item_id AND inventory.team_id = ?
    ORDER BY amount DESC;

在Django ORM中,没有办法使用自定义条件来表达外部连接。可以,您可以在Python循环中进行两个简单的独立查询并手动执行join。在这种情况下,性能可能不会受到太大影响。但这不是重点,因为只使用基本的SELECT就可以在应用程序端重现每个查询的结果。

使用SQLAlchemy:

class Account(Base):
    __tablename__ = 'account'
    id = Column(Integer, primary_key=True)
    ...

class Item(Base):
    __tablename__ = 'item'
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    ...

class Inventory(Base):
    __tablename__ = 'inventory'
    account_id = Column(Integer, ForeignKey('account.id'), primary_key=True,
            nullable=False)
    account = relationship(Account)
    item_id = Column(Integer, ForeignKey('item.id'), primary_key=True,
            nullable=False)
    item = relationship(Item)
    amount = Column(Integer, CheckConstraint('amount >= 0'), nullable=False,
            default=0)

account = session.query(Account).get(some_id)
result = (session
    .query(Item, func.coalesce(Inventory.amount, 0).label('amount'))
    .outerjoin(Inventory,
        and_(Item.id==Inventory.item_id, Inventory.account==account))
    .order_by(desc('amount'))
    .all())

顺便说一句,SQLAlchemy使得基于字典的集合非常容易。通过在Account模型中添加以下代码,您可以使与Inventory的关系看起来像它原来的样子:从项目到数量的映射。

items = relationship('Inventory',
    collection_class=attribute_mapped_collection('item_id'))
inventory = association_proxy('items', 'amount',
    creator=lambda k, v: Inventory(item_id=k, amount=v))

这使您能够编写代码,例如:

account.inventory[item_id] += added_value

它透明地插入或更新inventory表中的条目。

复杂的连接、子查询、窗口聚合- Django ORM无法在不使用原始SQL的情况下处理这些问题。

票数 69
EN

Stack Overflow用户

发布于 2017-01-19 06:31:08

这应该可以在Django 1.11中工作:

inventory_amount = Subquery(account.inventory_set.filter(item=OuterRef('pk')).values('amount'))
Item.objects.annotate(inventory_amount=Coalesce(inventory_amount, Value(0)))
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18199053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档