Django查询外键计数()零

Django查询外键计数()零,django,django-queryset,Django,Django Queryset,我有三张桌子: 卡车带有以下字段:id,name 菜单包含以下字段:id,itemname,id\u foodtype,id\u truck Foodtype带有以下字段:id,type 我想得到如下总结: id name total 10 Alcoholic drink 0 5 Appetizer 11 我的问题是返回带有0元素的结果 我尝试了如下SQL查询: SELECT ft.id, ft.name, COUNT(me.id)

我有三张桌子:

卡车带有以下字段:
id
name

菜单包含以下字段:
id
itemname
id\u foodtype
id\u truck

Foodtype带有以下字段:
id
type

我想得到如下总结:

id  name              total
10  Alcoholic drink   0
5   Appetizer         11
我的问题是返回带有
0
元素的结果

我尝试了如下SQL查询:

SELECT
    ft.id, ft.name, COUNT(me.id) total
FROM
    foodtype ft LEFT JOIN menu me
        ON ft.id = me.id_foodtype
    LEFT JOIN truck tr
        ON tr.id = me.id_truck AND tr.id = 3
GROUP BY ft.id, ft.name
ORDER BY ft.name
或Django中的查询

Menu.objects.filter(id_truck=3).values("id_foodtype").annotate(cnt=Count("id_foodtype"))
但是,这两种方法都没有使用
元素显示结果

在将此查询转换为Python时,我的任何查询都会返回我期望的准确结果。
如何使用
左连接返回结果,包括
菜单中零元素的
食物类型

左连接的方向取决于启动查询的对象。如果从
菜单启动
,您将永远不会看到所选菜单项未使用的
食物类型
。然后,重要的是(在您的情况下,通过卡车)进行过滤,允许使用null value Menu.id以获得Count==0

from django.db.models import Q
qs = (
    FoodType.objects
    .filter(Q(menu_set__id_truck=3) | Q(menu_set__id__isnull=True))
    .values()   # not necessary, but useful if you want a dict, not a Model object
    .annotate(cnt=models.Count("menu_set__id"))
)
验证:

>>> print(str(qs.query))
SELECT foodtype.id, foodtype..., COUNT(menu.id) AS cnt
FROM foodtype
LEFT OUTER JOIN menu ON (foodtype.id = menu.id_foodtype)
WHERE _menu.id_truck = 3 OR menu.id IS NULL)
GROUP BY foodtype.id
它适用于当前最新和最旧的Django 2.0b1和1.8

无论是否有行
.values()
,查询都是相同的。结果是具有
cnt
属性的字典或FoodType对象


脚注
如果定义了相关名称,则名称
菜单集
应替换为外键
id\u foodtype
的真实
相关名称

class Menu(models.Model):
    id_foodtype = models.ForeignKey('FoodType', on_delete=models.DO_NOTHING,
                                    db_column='id_foodtype', related_name='menu_set'))
    ...

如果启动一个新项目,我建议将外键重命名为不带“id”的名称,并且db_列字段带“id”。然后
menu\u item.foodtype
是一个食物对象,而
menu\u item.id\u foodtype
its
id

这更像是一个sql postgres的问题,而不是djangoI编辑了您的问题,以便于搜索,希望它是可以接受的。我也编辑了我的答案。