Django查询筛选器将AND和/或与Q对象组合不会返回预期结果

2024-05-15 13:53:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试使用Q对象在过滤器中组合AND和OR。看起来|的行为像一个和。这与以前在同一查询中运行而不是作为子查询运行的注释有关。

对Django来说,正确的处理方法是什么?

型号.py

class Type(models.Model):
    name = models.CharField(_('name'), max_length=100)
    stock = models.BooleanField(_('in stock'), default=True)
    hide = models.BooleanField(_('hide'), default=False)
    deleted = models.BooleanField(_('deleted'), default=False)

class Item(models.Model):
    barcode = models.CharField(_('barcode'), max_length=100, blank=True)
    quantity = models.IntegerField(_('quantity'), default=1)
    type = models.ForeignKey('Type', related_name='items', verbose_name=_('type'))

视图.py

def hire(request):
    categories_list = Category.objects.all().order_by('sorting')
    types_list = Type.objects.annotate(quantity=Sum('items__quantity')).filter(
        Q(hide=False) & Q(deleted=False),
        Q(stock=False) | Q(quantity__gte=1))
    return render_to_response('equipment/hire.html', {
           'categories_list': categories_list,
           'types_list': types_list,
           }, context_instance=RequestContext(request))

生成的SQL查询

SELECT "equipment_type"."id" [...] FROM "equipment_type" LEFT OUTER JOIN
    "equipment_subcategory" ON ("equipment_type"."subcategory_id" =
    "equipment_subcategory"."id") LEFT OUTER JOIN "equipment_item" ON
    ("equipment_type"."id" = "equipment_item"."type_id") WHERE 
    ("equipment_type"."hide" = False AND "equipment_type"."deleted" = False )
    AND ("equipment_type"."stock" = False )) GROUP BY "equipment_type"."id"
    [...] HAVING SUM("equipment_item"."quantity") >= 1

需要SQL查询

SELECT
    *
FROM
    equipment_type
LEFT JOIN (
    SELECT type_id, SUM(quantity) AS qty
    FROM equipment_item
    GROUP BY type_id
) T1
ON id = T1.type_id
WHERE hide=0 AND deleted=0 AND (T1.qty > 0 OR stock=0)

编辑:我添加了预期的SQL查询(不带设备连接子类别)


Tags: andnameidfalsedefaultmodelstypestock
3条回答

尝试添加括号以显式指定分组?正如您已经知道的,到filter()的多个参数只是通过和在底层SQL中连接起来的。

最初你有这个过滤器:

[...].filter(
    Q(hide=False) & Q(deleted=False),
    Q(stock=False) | Q(quantity__gte=1))

如果你想要(A&B&C&D),那么这应该是可行的:

[...].filter(
    Q(hide=False) & Q(deleted=False) &
    (Q(stock=False) | Q(quantity__gte=1)))

好吧,在这里或在django没有成功。所以我选择使用原始的SQL查询来解决这个问题。。。

这里是工作代码:

types_list = Type.objects.raw('SELECT * FROM equipment_type
    LEFT JOIN (                                            
        SELECT type_id, SUM(quantity) AS qty               
        FROM equipment_item                                
        GROUP BY type_id                                   
    ) T1                                                   
    ON id = T1.type_id                                     
    WHERE hide=0 AND deleted=0 AND (T1.qty > 0 OR stock=0) 
    ')

这个答案很晚了,但对很多人都有帮助。

[...].filter(hide=False & deleted=False)
.filter(Q(stock=False) | Q(quantity__gte=1))

这将产生类似于

WHERE (hide=0 AND deleted=0 AND (T1.qty > 0 OR stock=0))

相关问题 更多 >