Django中相关字段的查询Q()不能作为'set contains'? [英] Query Q() is not working as 'set contain' for related field in Django?

查看:146
本文介绍了Django中相关字段的查询Q()不能作为'set contains'?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有水果篮子。如何过滤那些包含所有水果的篮子?



在本文档中 https://docs.djangoproject.com/en/dev/ref/models/querysets/#in
'in'方法似乎会返回任何包含任何给定水果的篮子。
是否有任何set_contains方法用于过滤?如Basket.objects.filter(fruit_set_containsAll = fruitSet)?



编辑:我发现Q()是不正常工作。我将在这里发布测试:

  class Basket(models.Model):
weight = models.FloatField default = 1)
class Fruitname(models.Model):
name = models.CharField(max_length = 32)
class Fruit(models.Model):
ofkind = models。 ForeignKey(Fruitname,on_delete = models.CASCADE)
inbasket = models.ForeignKey(Basket,on_delete = models.CASCADE)
weight = models.FloatField(default = 1)

数据库仅在1个篮子中设置为苹果,2个篮子中的梨,3个篮子中的banana / p>

 打印Basket.objects.all()
打印Fruitname.objects.all()
[篮子:id 31有4个水果
1. id - 53 apple(28),weight 1.00
2. id - 54 apple(28),weight 2.00
3. id - 55 apple 28),重量3.00
4. id - 62香蕉(30),重量10.00
>,< Basket:id 32有2个水果
1. id - 56 pear(29) ,体重4.00
2. id - 57香蕉(30),重量5.00
>,<篮子:id 33有4个水果
1. id - 58梨(29),体重6.00
2. id - 59香蕉(30),体重7.00
3. id - 60 pear(29),weight 8.00
4. id - 61 pear(29),weight 9.00
>]
[< Fruitname:apple 28)>< Fruitname:pear(29)>< Fruitname:banana(30)>]

如果我尝试用'apple'和'banana'查询,它会给出空集!!

 打印Basket.objects.filter(Q(fruit__ofkind__name__in = ['apple'])& Q(fruit__ofkind__name__in = ['banana']))distinct()
[]

同样,

 打印Basket.objects。过滤器(Q(fruit__ofkind__name__in = ['banana'])&Q(fruit__ofkind__name__in = ['pear']))distinct()
[]

这是我如何使用'in'过滤,这不是我需要的,应该是一个空集。

 打印Basket.objects.filter(Q (fruit__ofkind__name__in = ['apple','pear']))。distinct()
[< Basket:id 31有4个水果
1. id - 53 apple(28),weight 1.00
2. id - 54 apple(28),weight 2.00
3. id - 55 apple(28),weight 3.00
4. id - 62 banana(30),weight 10.00
>< Basket:id 32具有2个水果
1. id - 56 pear(29),weight 4.00
2. id - 57 banana(30),weight 5.00
> ,< Basket:id 33有4个水果
1. id - 58 pear(29),weight 6.00
2. id - 59 banana(30),weight 7.00
3. id - 60梨(29),体重8.00
4. id - 61梨(29),体重9.00
>]

正常工作的唯一方法是使用过滤器链接:

  Basket.objects。 filter(fruit__ofkind__name__in = ['apple'])filter(fruit__ofkind__name__in = ['banana'])。distinct()
[< Basket:id 31有4个水果
1. id - 53 apple 28),weight 1.00
2. id - 54 apple(28),weight 2.00
3. id - 55 apple(28),weight 3.00
4. id - 62 banana(30),weight 10.00
>]

这些代码用Django 1.9.4
测试任何解释?我会撤销现在接受的答复。

解决方案

通过打印Q&操作,我已经找到了为什么Q正在这样工作的原因。

 从django.db导入连接
打印connection.queries
u'SELECT DISTINCTmarket_basketid,market_basket。weightFROMmarket_basketINNER JOINmarket_fruitON(market_basketid=market_fruit。 (market_fruitname,id)WHERE(market_fruitname,nameIN(\'apple\')ANDmarket_fruitname)INNER JOINmarket_fruitnameON(market_fruitofkind_id=market_fruitname nameIN(\'banana\'))LIMIT 21'

关键问题是在单个过滤器中使用查询时, WHERE 子句将不会在单个条件下满足。它实际上是寻找一个 fruitname 是在['apple']和['banana'],这是不可能的。需要的是找到(那些具有苹果水果名称的水果)或(具有香蕉果实的水果)



目前唯一可行的解​​决方案是链式过滤器。


Let's say we have baskets of fruits. How to filter out those baskets that contains all fruits in a given basket?

In this document https://docs.djangoproject.com/en/dev/ref/models/querysets/#in 'in' method seems will return any basket which contains any of the given fruit. Is there any "set_contains" method to be used for filtering ? Such as Basket.objects.filter(fruit_set_containsAll=fruitSet) ?

Edit: I found that Q() is not working as expected. I'll post the test here:

class Basket(models.Model):
    weight = models.FloatField(default=1)
class Fruitname(models.Model):
    name = models.CharField(max_length=32)
class Fruit(models.Model):
    ofkind = models.ForeignKey(Fruitname, on_delete=models.CASCADE)  
    inbasket = models.ForeignKey(Basket, on_delete=models.CASCADE)  
    weight = models.FloatField(default=1)

the database is set as 'apple' only in 1 basket, 'pear' in 2 baskets, and 'banana' in 3 basket:

print Basket.objects.all()
print Fruitname.objects.all()
[<Basket: id 31 has 4 fruits 
    1. id - 53 apple(28), weight 1.00
    2. id - 54 apple(28), weight 2.00
    3. id - 55 apple(28), weight 3.00
    4. id - 62 banana(30), weight 10.00
>, <Basket: id 32 has 2 fruits 
    1. id - 56 pear(29), weight 4.00
    2. id - 57 banana(30), weight 5.00
>, <Basket: id 33 has 4 fruits 
    1. id - 58 pear(29), weight 6.00
    2. id - 59 banana(30), weight 7.00
    3. id - 60 pear(29), weight 8.00
    4. id - 61 pear(29), weight 9.00
>]
[<Fruitname: apple(28)>, <Fruitname: pear(29)>, <Fruitname: banana(30)>]

If I try to query with 'apple' and 'banana', it gives empty set !!

print Basket.objects.filter(Q(fruit__ofkind__name__in=['apple'])&Q(fruit__ofkind__name__in=['banana'])).distinct()
[]

similarly,

print Basket.objects.filter(Q(fruit__ofkind__name__in=['banana'])&Q(fruit__ofkind__name__in=['pear'])).distinct()
[]

Here's how I use 'in' to filter, it is not what I need which is supposed to be an empty set.

print Basket.objects.filter(Q(fruit__ofkind__name__in=['apple','pear'])).distinct()
[<Basket: id 31 has 4 fruits 
    1. id - 53 apple(28), weight 1.00
    2. id - 54 apple(28), weight 2.00
    3. id - 55 apple(28), weight 3.00
    4. id - 62 banana(30), weight 10.00
>, <Basket: id 32 has 2 fruits 
    1. id - 56 pear(29), weight 4.00
    2. id - 57 banana(30), weight 5.00
>, <Basket: id 33 has 4 fruits 
    1. id - 58 pear(29), weight 6.00
    2. id - 59 banana(30), weight 7.00
    3. id - 60 pear(29), weight 8.00
    4. id - 61 pear(29), weight 9.00
>]

The only way that is working properly is chaining with filter:

Basket.objects.filter(fruit__ofkind__name__in=['apple']).filter(fruit__ofkind__name__in=['banana']).distinct()
[<Basket: id 31 has 4 fruits 
    1. id - 53 apple(28), weight 1.00
    2. id - 54 apple(28), weight 2.00
    3. id - 55 apple(28), weight 3.00
    4. id - 62 banana(30), weight 10.00
>]

These code is tested with Django 1.9.4 Any explaining? I would undo the accepted answer for the moment.

解决方案

By printing the raw SQL of the Q & operations, I've found the reason why Q is working as this.

from django.db import connection
print connection.queries
u'SELECT DISTINCT "market_basket"."id", "market_basket"."weight" FROM "market_basket" INNER JOIN "market_fruit" ON ("market_basket"."id" = "market_fruit"."inbasket_id") INNER JOIN "market_fruitname" ON ("market_fruit"."ofkind_id" = "market_fruitname"."id") WHERE ("market_fruitname"."name" IN (\'apple\') AND "market_fruitname"."name" IN (\'banana\')) LIMIT 21'

the key problem is WHERE clause will not be satisfied in a single condition when queries is used in a single filter. It is actually looking for a fruitname is both in ['apple'] and ['banana'] which is not possible. What is needed is to find (those fruits that have fruitname of 'apple') or (those fruits that have fruitname of 'banana')

Currently the only viable solution is to chain filters.

这篇关于Django中相关字段的查询Q()不能作为'set contains'?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆