2017-08-31 88 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() 

但是,當然,這不是你想要的,你所需的字段進行篩選使得前聯盟。