Python 基于FK的Django查询&x2014;得到全部,而不是全部

Python 基于FK的Django查询&x2014;得到全部,而不是全部,python,mysql,django,Python,Mysql,Django,我需要找到状态为“已完成”的所有订单项的订单。看起来是这样的: FINISHED_STATUSES = [17,18,19] if active_tab == 'outstanding': orders = orders.exclude(items__status__in=FINISHED_STATUSES) 但是,此查询仅为我提供带有任何状态为“已完成”的订单项的订单。我该如何进行查询,以便仅检索那些具有所有状态为“已完成”的订单项目的订单?我认为您需要在此处进行原始查询: 将订单和

我需要找到状态为“已完成”的所有订单项的订单。看起来是这样的:

FINISHED_STATUSES = [17,18,19]
if active_tab == 'outstanding':
    orders = orders.exclude(items__status__in=FINISHED_STATUSES)

但是,此查询仅为我提供带有任何状态为“已完成”的订单项的订单。我该如何进行查询,以便仅检索那些具有所有状态为“已完成”的订单项目的订单?

我认为您需要在此处进行原始查询:

将订单和项目模型设置为订单和项目:

# raw query
sql = """\
  select `orders`.* from `%{orders_table}s` as `orders`
  join `%{items_table}s` as `items`
  on `items`.`%{item_order_fk}s` = `orders`.`%{order_pk}s`
  where `items`.`%{status_field}s` in (%{status_list}s)
  group by `orders`.`%{orders_pk}s`
  having count(*) = %{status_count)s;
""" % {
        "orders_table": Orders._meta.db_table,
        "items_table":  Items._meta.db_table,
        "order_pk":     Orders._meta.pk.colum,
        "item_order_fk":Items._meta.get_field("order").colum,
        "status_field": Items._meta.get_field("status").colum,
        "status_list":  str(FINISHED_STATUSES)[1:-1],
        "status_count": len(FINISHED_STATUSES),
    }

orders = Orders.objects.raw(sql)

我认为您需要在这里进行原始查询:

将订单和项目模型设置为订单和项目:

# raw query
sql = """\
  select `orders`.* from `%{orders_table}s` as `orders`
  join `%{items_table}s` as `items`
  on `items`.`%{item_order_fk}s` = `orders`.`%{order_pk}s`
  where `items`.`%{status_field}s` in (%{status_list}s)
  group by `orders`.`%{orders_pk}s`
  having count(*) = %{status_count)s;
""" % {
        "orders_table": Orders._meta.db_table,
        "items_table":  Items._meta.db_table,
        "order_pk":     Orders._meta.pk.colum,
        "item_order_fk":Items._meta.get_field("order").colum,
        "status_field": Items._meta.get_field("status").colum,
        "status_list":  str(FINISHED_STATUSES)[1:-1],
        "status_count": len(FINISHED_STATUSES),
    }

orders = Orders.objects.raw(sql)

我能用一种很普通的方式完成这件事。首先,我添加了一个额外的布尔列,
is\u finished
。然后,要查找至少包含一个未完成项的订单:

orders = orders.filter(items__status__is_finished=False)
这给了我所有未完成的订单

执行与此相反的操作将获得已完成的订单:

orders = orders.exclude(items__status__is_finished=False)

我能用一种很普通的方式完成这件事。首先,我添加了一个额外的布尔列,
is\u finished
。然后,要查找至少包含一个未完成项的订单:

orders = orders.filter(items__status__is_finished=False)
这给了我所有未完成的订单

执行与此相反的操作将获得已完成的订单:

orders = orders.exclude(items__status__is_finished=False)

添加布尔字段是一个好主意。这样,您就可以在模型中清晰地定义业务规则

现在,假设您仍然希望在不添加字段的情况下执行此操作。考虑到不同的情况,这很可能是一项要求。不幸的是,您不能在Django ORM中真正使用子查询或任意联接。但是,您可以构建
Q
对象,并使用
filter()
annotate()
在having子句中进行隐式连接

来自django.db.models.aggregates导入计数
从django.db.models导入Q
从functools导入reduce
从操作员导入或_
按订单列出的项目总数=订单.objects.annotate(
项目\计数=计数(“项目”)
按订单完成的项目=订单.objects.filter(
项目状态=完成状态)。注释(
项目\计数=计数(“项目”)
订单=按订单列出的项目总数。排除(
减少(或减少,(id=o.id,项目数量=o.item数量)
对于完工项目(按订单)中的o)

请注意,使用原始SQL虽然不那么优雅,但通常效率更高。

添加布尔字段是一个好主意。这样,您就可以在模型中清晰地定义业务规则

现在,假设您仍然希望在不添加字段的情况下执行此操作。考虑到不同的情况,这很可能是一项要求。不幸的是,您不能在Django ORM中真正使用子查询或任意联接。但是,您可以构建
Q
对象,并使用
filter()
annotate()
在having子句中进行隐式连接

来自django.db.models.aggregates导入计数
从django.db.models导入Q
从functools导入reduce
从操作员导入或_
按订单列出的项目总数=订单.objects.annotate(
项目\计数=计数(“项目”)
按订单完成的项目=订单.objects.filter(
项目状态=完成状态)。注释(
项目\计数=计数(“项目”)
订单=按订单列出的项目总数。排除(
减少(或减少,(id=o.id,项目数量=o.item数量)
对于完工项目(按订单)中的o)

请注意,使用原始SQL虽然不那么优雅,但通常效率更高。

我不知道为什么有人投票结束这个问题。我认为这是有价值的。我不知道为什么有人投票结束这个问题。我认为它有优点。回答得好,因为Django ORM不支持group by。回答得好,因为Django ORM不支持group by。这可能是解决问题的最好方法。我不会认为它是陈腐的——我会考虑重构你的设计。如果你将来遇到类似的情况,看看我修改过的答案。这可能是解决你问题的最好办法。我不会认为它是陈腐的——我会考虑重构你的设计。如果你将来遇到类似的情况,请查看我修改后的答案。