我正在尝试按com_proc
变量进行过滤,但它不起作用...
这里的复杂性是过滤器可以多次包含 同一个对象。这是我的代码:
class Act(models.Model):
com_proc=models.CharField(max_length=100, blank=True, null=True, default=None)
cs_1=models.ForeignKey(CodeSect, related_name='code_sect_1', blank=True, null=True, default=None)
cs_2=models.ForeignKey(CodeSect, related_name='code_sect_2', blank=True, null=True, default=None)
cs_3=models.ForeignKey(CodeSect, related_name='code_sect_3', blank=True, null=True, default=None)
class ActIds(models.Model):
propos_origine=models.CharField(max_length=4, blank=True, null=True, default=None)
act=models.ForeignKey(Act)
qs_acts=ActIds.objects.none()
len(qs_acts)
for act in ActIds.objects.all():
#loop over each cs variable
for nb in range(1,4):
code_sect=getattr(act.act, "cs_"+str(nb))
if code_sect is not None:
qs_acts._result_cache.append(act)
print "qs_acts"
for act in qs_acts:
print act.pk, act.act.com_proc, act.propos_origine
我使用动态queryset
和_result_cache
,因为每个对象最多可以在过滤器中出现三次(每个cs
变量一次)。我不知道如何使用正常过滤重现它。
输出:
9429 Oral procedure COM
9429 Oral procedure COM
9697 Written procedure COM
12352 Written procedure COM
12362 Oral procedure COM
代码:
...
print filter_vars_periods
输出:
{'act__com_proc': 'Written procedure', 'propos_origine': 'COM', 'act__adopt_conseil__gte': datetime.date(2009, 12, 1), 'act__adopt_conseil__lte': datetime.date(2013, 12, 31)}
代码:
temp_filter=qs_acts.filter(**filter_vars_periods)
for act in temp_filter:
print act.pk, act.act.com_proc, act.propos_origine
输出:
9429 Oral procedure COM
9429 Oral procedure COM
9697 Written procedure COM
12352 Written procedure COM
12362 Oral procedure COM
你可以看到com_proc="Written procedure"
的过滤不起作用,我在最后得到了相同的查询集。为什么呢?
我想我知道为什么两个连续的过滤不能给出预期的输出:
Chaining multiple filter() in Django, is this a bug?
据说使用两个过滤器不等同于逻辑AND
,而是等同于逻辑OR
。这可能是我的第二个过滤器没有过滤任何东西的原因......
无论如何,我仍然不知道如何解决我的问题:(。
答案 0 :(得分:0)
我认为不可能使用多次存储相同对象的查询集。 相反,我使用列表:
class Act(models.Model):
com_proc=models.CharField(max_length=100, blank=True, null=True, default=None)
cs_1=models.ForeignKey(CodeSect, related_name='code_sect_1', blank=True, null=True, default=None)
cs_2=models.ForeignKey(CodeSect, related_name='code_sect_2', blank=True, null=True, default=None)
cs_3=models.ForeignKey(CodeSect, related_name='code_sect_3', blank=True, null=True, default=None)
class ActIds(models.Model):
propos_origine=models.CharField(max_length=4, blank=True, null=True, default=None)
act=models.ForeignKey(Act)
qs_acts=[]
for act in ActIds.objects.all():
#loop over each cs variable
for nb in range(1,4):
code_sect=getattr(act.act, "cs_"+str(nb))
if code_sect is not None:
qs_acts.append(act)
然后问题是我不能再做以下事了:
temp_filter=qs_acts.filter(**filter_vars).exclude(**exclude_vars)
相反,我创建了一个翻译django语法的函数:
def filter_exclude_list(list_acts, filter_vars={}, exclude_vars={}):
list_acts_new=[]
for act in list_acts:
ok=True
for key, value in filter_vars.iteritems():
#related object: "act__validated_attendance":1
if key[:5]=="act__":
key=key[5:]
instance=act.act
else:
instance=act
#greater than or equal: "nb_point_a__gte": 1
if key[-5:]=="__gte":
if getattr(instance, key[:-5])<value:
ok=False
break
#"com_amdt_tabled__isnull": False
elif key[-8:]=="__isnull":
if getattr(instance, key[:-8]) is None:
ok=False
break
#equal to: "nb_point_a": 1
elif getattr(instance, key) != value:
ok=False
break
if ok:
for key, value in exclude_vars.iteritems():
#"adopt_cs_abs": None
if key=="adopt_cs_abs" and value is None:
if not getattr(instance, key).exists():
ok=False
break
#different from: "nb_point_a": 1
elif getattr(instance, key) == value:
ok=False
break
if ok:
list_acts_new.append(act)
return list_acts_new
然后我可以做:
qs_acts_new=filter_exclude_list(qs_acts, filter_vars=filter_vars, exclude_vars=exclude_vars)
这有效,但我发布这个希望有人有一个更好,更简洁的解决方案:)。