2017-08-09 74 views
0

我目前正在用注释和包含的运算符来操作django querysets的行为|和&在合并两个查询集后保留queryset注释

我有模式是这样的:

class Property(models.Model): 
    value = models.IntegerField(null=True) 

    obj = PropertyManager() 

class Profile(models.Model): 
    name = models.CharField() 
    values = models.ManyToManyField(Property) 

class PropertyManager(models.Manager): 
    def included(self, profile): 
     super(PropertyManager, self).filter(Q(property__profile=profile)).annotate(included_value=Value('true', output_field=CharField())) 

    def excluded(self, profile): 
     super(PropertyManager, self).filter(~Q(property__profile=profile)).annotate(included_value=Value('false', output_field=CharField())) 

    def included_excluded(self, profile): 
     return (self.excluded(profile) | self.included(profile)).distinct() 

我天真地预计included_excluded函数返回与他们的注释都查询集的加入queryset的,如:

property_id | included_value 
------------|--------------- 
      1 | true 
      2 | false 

但事实证明, ,我的示例中注释被覆盖:

j = Profile.objects.get(id=1) 
exc = Property.obj.excluded(profile=j) 
inc = Property.obj.included(profile=j) 
all = Property.obj.included_excluded(profile=j) 

len(inc) => 14 
len(exc) => 17 
len(all) => 31 

all.values_list("included_value") => <QuerySet [('false',)]> 
exc.values_list("included_value") => <QuerySet [('false',)]> 
inc.values_list("included_value") => <QuerySet [('true',)]> 
如我所料,

all显然不是所有注解中的正确值。

所以我想知道,如果有连接两个查询集,并保持我前面

回答

0

从Django的1.8所作的注释的方法向上,你可以做这样的:

from django.db import models 
from django.db.models import Case, When 

def included_excluded(self, profile): 
    return super(PropertyManager, self).annotate(
     included_value=Case(
      When(property__profile=profile, then='true'), 
      default='false', output_field=models.CharField() 
     ) 
    ) 

如果您分别需要它们,那么稍后您可以过滤此查询集:PropertyManager().included_excluded(profile).filter(included_value='true')