2017-08-31 90 views
0

这里有一个基本的多对多的关系模型:Django的联盟

from django.db import models                  

class ManyToManyModel(models.Model):                
    name = models.CharField(max_length=50)              

class MainModel(models.Model):                 
    name = models.CharField(max_length=50)              
    many_to_many_ref = models.ManyToManyField(ManyToManyModel) 

我创建这些型号如下的情况下,追平了ManyToManyModel实例MainModel实例:

from app1.models import ManyToManyModel, MainModel 
m2m1 = ManyToManyModel(name='Number 1') 
m2m1.save() 
m2m2 = ManyToManyModel(name='Number 2') 
m2m2.save() 
m2m3 = ManyToManyModel(name='Number 3') 
m2m3.save() 
m2m4 = ManyToManyModel(name='Number 4') 
m2m4.save() 

mm1 = MainModel(name='Main 1') 
mm1.save() 
mm1.many_to_many_ref.add(m2m1) 
mm1.save() 

mm2 = MainModel(name='Main 2') 
mm2.save() 
mm2.many_to_many_ref.add(m2m1) 
mm2.many_to_many_ref.add(m2m2) 
mm2.many_to_many_ref.add(m2m3) 
mm2.save() 

mm3 = MainModel(name='Main 3') 
mm3.save() 
mm3.many_to_many_ref.add(m2m4) 
mm3.save() 

现在,我想获得与构建的所有MainModel对象关联的所有的的Queryset。有可能是一个更好的方式来做到这一点,但这个例子使用union(新在Django 1.11):

for mm in MainModel.objects.all(): 
    try: 
     m2m_union = m2m_union.union(mm.many_to_many_ref.all()) 
    except NameError: 
     m2m_union = mm.many_to_many_ref.all() 

现在,m2m_union包含在其查询集四个条目,但让我们过滤掉一个,我在乎,例如这个查询只能与name='Number 1'返回ManyToManyModel

m2m_union.get(name__endswith='1') 

这将返回以下错误:

Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File ".../lib/python3.6/site-packages/django/db/models/query.py", line 384, in get 
    (self.model._meta.object_name, num) 
app1.models.MultipleObjectsReturned: get() returned more than one ManyToManyModel -- it returned 4! 

但是,如果我直接查询的ManyToManyModel实例,并尝试获取对象的方式,它的工作原理:

ManyToManyModel.objects.all().get(name__endswith='1') 

为什么由迭代union创建的查询集的行为不一样?

回答

1

做完union后无法过滤。如前所述in the documentation

... only LIMIT, OFFSET, COUNT(*), and ORDER BY (i.e. slicing, count(), and order_by()) are allowed on the resulting QuerySet. Further, databases place restrictions on what operations are allowed in the combined queries. For example, most databases don’t allow LIMIT or OFFSET in the combined queries.

你的情况,你实际上可以得到你想要与对象:

m2m_union.order_by('name').first() 

但是,当然,这不是你想要的,你所需的字段进行筛选使得前联盟。