Django多字段搜索表单

0 投票
1 回答
2364 浏览
提问于 2025-04-18 15:59

我有一个查询表单,这个表单有三个输入框,可以从数据库中显示相关的匹配内容。不过,我想只选择这三个输入框中的一个,然后从数据库中获取与这个输入框相关的数据。

views.py

from django.shortcuts import render
from search.forms import ModuleForm
from django.http import HttpResponse
from search.models import Module,Metamodule,Release

def searchview(request):
     if request.method == 'GET':
        form = ModuleForm(request.GET)  
        if form.is_valid():
           release_num = form.cleaned_data['release_num']
           metamodule_name = form.cleaned_data['metamodule_name']
           module_name = form.cleaned_data['module_name']
           results =    Module.objects.filter(metamodule__release__number=release_num).filter(metamodule__name=metamodule_name).filter(name=module_name)
           return render(request,'search/search_result.html',{'form': form, 'results': results})
     else:
          form = ModuleForm()    
          return render(request, 'search/search_form.html',{'form': form})

forms.py

from django import forms
from search.models import Module,Release,Metamodule

class ModuleForm(forms.Form):
     release_num = forms.ModelChoiceField(queryset=Release.objects.all(),empty_label='Pick a Release')
     metamodule_name = forms.ModelChoiceField(queryset=Metamodule.objects.all(),empty_label='Pick a Meta module')
     module_name = forms.ModelChoiceField(queryset=Module.objects.all(),empty_label='Pick a Module')

     def clean_release_number(self):
       try:
          release_num = self.cleaned_data.get["release_num"]
          metamodule_name = int(self.cleaned_data["metamodule_name"])
          module_name = int(self.cleaned_data["module_name"])
       except:
          release_num = None
          metamodule_name = None
          module_name = None

       if release_num and    Module.objects.exclude(metamodule__release__number=release_num).exists():
           raise forms.ValidationError("Please enter a valid release number.")
       else:
           return release_num          

我该如何修改视图,让它只接受一个输入,并且即使另外两个输入框没有填写数据,也能显示相关的数据呢?

1 个回答

0

考虑对每个字段进行检查,并根据该字段的值进行过滤。

if form.is_valid():
    release_num = form.cleaned_data['release_num']
    metamodule_name = form.cleaned_data['metamodule_name']
    module_name = form.cleaned_data['module_name']
    results = Module.objects.all()
    if release_num:
        results = results.filter(metamodule__release__number=release_num)
    if metamodule_name:
        result = results.filter(metamodule__name=metamodule_name)
    if module_name:
        result = results.filter(name=module_name)
    return render(request,'search/search_result.html',{'form': form, 'results': results})

你需要用自己的 clean_fieldname() 方法来验证输入。可以考虑使用 def clean(self) 来进行多个字段的验证(比如确保至少有一个字段被填写)。

你为什么要用 GET 来处理表单输入呢?有没有什么特别的原因让你选择用 GET 提交表单数据,而不使用 POST 呢?

另外,虽然你检查了 form.is_valid() 并实现了 clean_fieldname 方法,但你还需要在 if form.is_valid(): 后面加一个 else 分支,用来处理 form.errors

撰写回答