django q对象和更高级的搜索

时间:2014-02-03 08:26:33

标签: django forms django-queryset django-q

我有这样的模型

class Customer(models.Model):
    #fields
    doctor = models.ForeignKey(Doctor)

我想创建一个搜索客户表单,因此我创建了一个新表单(不是ModelForm,因为我只希望表单的字段而不是save方法),其中包含客户的字段。我想要实现的功能是:

  • 如果表单为空,用户按下搜索显示所有客户
  • 如果表单包含数据字段,请执行AND搜索字段

我为测试傀儡实现的搜索字段是以下first_name,last_name和doctor。我使用了像这样的Q对象:

if customer_form.is_valid():
    post_data = customer_form.cleaned_data
    customers = Customer.objects.filter(
        Q(first_name__icontains=post_data['first_name']) &
        Q(last_name__icontains=post_data['last_name']) &
        Q(doctor=post_data['doctor'])
    )
当我没有在所选择的领域中选择医生时,它不会工作。如果我删除

Q(doctor-post_data['doctor']

搜索按预期工作。如果我按原样离开并从表格的选择领域中选择一名医生那么它可以工作但不是我想要的。为什么增加医生打破功能?

The form is:

class CustomerSearchForm(Form):
    #form fields
    doctor = forms.ModelChoiceField (required=False, queryset=Doctor.objects.all(), widget=Select(attrs={"class":"form-control input-sm"}))

有什么不对?

1 个答案:

答案 0 :(得分:1)

您可以有条件地撰写Q表达式:

qexpr = ( Q(first_name__icontains=post_data['first_name']) &
          Q(last_name__icontains=post_data['last_name']) )
if post_data['doctor']:
    qexpr &= Q(doctor=post_data['doctor'])
customers = Customer.objects.filter(qexpr)

doctor=post_data['doctor']上的无条件过滤器将评估为doctor=None,如果您在表单的doctor输入中未选择任何内容,则会转换为doctor_id = NULL或{生成的SQL查询中的{1}}(不确定Django的ORM如何处理它,我还没有测试过),它们都不匹配模型中的任何记录。