Django python - **之后的filter()参数必须是映射,而不是str

时间:2015-07-08 19:23:52

标签: python django django-forms

我试图在forms.py中动态创建查询。我将它存储为字符串,然后尝试过滤并返回它,但我收到错误...

filter() argument after ** must be a mapping, not str

发生了什么事?显然它并不喜欢它。它应该是不同的数据类型吗?

forms.py

from django import forms
from django.db.models import Q

from .models import Incident
from .models import Equipment


class IncidentForm(forms.Form):
    incident_id = forms.IntegerField(required=False)
    equipment_id = forms.ModelChoiceField(Equipment.objects.all(), required=False, widget=forms.TextInput)

    def search(self):

        # cleaning the data
        cust_id = self.cleaned_data.get('incident_id')
        equip_id = self.cleaned_data.get('equipment_id')

        user_input = [cust_id, equip_id]

        # finding blank fields
        i = 0
        lst=[]
        for x in user_input:
            if x != None:
                lst.append(i)
            i += 1

        # setting up query with non blank data
        query = ""
        for x in lst:
            if x == 0:
                query += 'Q(id=cust_id)'
            if x == 1:
                query += 'Q(equipment_id=equip_id)'

        # replace all instances of ')' with ') & '. Also removed the last &
        new_query = query.replace(")", ") & ")
        new_query = new_query[:-3]

        print (new_query)

        return Incident.objects.filter(**new_query)

2 个答案:

答案 0 :(得分:5)

Q个对象是实际对象。它们不是你用字符串写的迷你语言。你应该使用:

query = Q()

for x in lst:
    if x == 0:
        query &= Q(id=cust_id)
    if x == 1:
        query &= Q(equipment_id=equip_id)

return Incident.objects.filter(query)

这看起来像是一种过度设计的方式来实现你想要做的事情。怎么样:

def search(self):
    cust_id = self.cleaned_data.get('incident_id')
    equip_id = self.cleaned_data.get('equipment_id')

    qs = Incident.objects.all()
    if cust_id is not None:
        qs = qs.filter(id=cust_id)
    if equip_ip is not None:
        qs = qs.filter(equipement_id=equip_id)

    return qs

答案 1 :(得分:0)

这是因为filter没有将字符串作为过滤器。相反,您应该传递Q对象或关键字过滤器(如django文档中所述)。在您的情况下,您可以动态创建最终查询:

query = Q()
for x in lst:
    if x == 0:
        query &= Q(id=cust_id)
    if x == 1:
        query &= Q(equipment_id=equip_id)

print (query)
return Incident.objects.filter(query)

&=运算符会创建新的Q对象,该对象代表左手侧和右手侧的AND