简体   繁体   中英

Django multiple field search form

I have a query form which gets input from 3 fields and display the related matched content from the database models. But i am trying to select only one field from the three fields on the form and need to get data from database models related to that field?

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          

How to modify the view to accept single input and display the data even though the other two fields are not provided with data?

Consider checking for each field and filtering on that field value individually.

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})

It's up to you to validate the input using your clean_fieldname() methods. Consider using def clean(self) to perform multi-field validation (like having at least one field filled in).

Why are you processing your form input on GET ? Is there a reason why you're submitting form data with GET and ignoring POST ?

Also, while it's good that you're checking form.is_valid() and implementing clean_fieldname methods, you need to add an else clause to if form.is_valid(): that handles form.errors .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM