Django model search form

First, I did my homework and looked around before posting! My question seems to be a very simple thing that should have been considered before.

Now I consider Django-filter as a potential solution, but I would like to get some advice if this is the right way and if there are other solutions.

I have a Django application with 10 models, each model has several fields. In most fields, ChoiceFieldusers fill out forms using the selectdefault widget . There is a separate form for each model.

I want to create a separate form for each model (in separate views) that users will use to search the database. The search form will contain only drop-down windows (widgets select) with the same options as the forms used to populate the database by adding the "any" option.

I know how to use it .object.filter(), however the “any” option will correspond to not including certain fields in the filter, and I'm not sure how to add model fields to the filter based on user selection

I looked briefly at Haystack as an option, but it seems for full-text search, and not for "simulated search", I am after.

Sample model (simplified):

class Property():             
      TYPE_CHOICES = (‘apartment’, ‘house’, ‘flat’)        
      type = charfield(choices=TYPE_CHOICES)
      LOC_CHOICES = (‘Brussels’, ‘London’, ‘Dublin’, ‘Paris’)
      location = charfield(choices=LOC_CHOICES)
      price = PostivieInteger()

"", "" ( ), 3 :

Property.objects.filter(type=’apartment’)
Property.objects.filter(location=’Dublin’)
Property.objects.filter(type=’apartment’, location=’Dublin’)

: django-filter?

Question 1: what’s the best option of accomplishing this overall? 
Question 2: how do I add model fields to the filter based on user’s form selection?
Question 3: how do I do the filter based on user selection? (I know how to use .filter(price_lt=).exclude(price_gt=) but again how do I do it dynamically based on selection as "ANY" would mean this is not included in the query)
+4
2

, ( ), , ... select_related prefetch_related

/forms.py:

class SearchPropertyForm(forms.Form):

    property_type = forms.ModelChoiceField(label=_("Property Type"), queryset=HouseType.objects.all(),widget=forms.Select(attrs={'class':'form-control input-sm'}))
    location = forms.ModelChoiceField(label=_('Location'), queryset=HouseLocation.objects.all(), widget=forms.Select(attrs={'class':'form-control input-sm'}))

/views.py

# Create a Mixin to inject the search form in our context 

class SeachPropertyMixin(object):
    def get_context_data(self, **kwargs):
        context = super(SeachPropertyMixin, self).get_context_data(**kwargs)
        context['search_property_form'] = SearchPropertyForm()
        return context

( :

# Use Class Based views, saves you a great deal of repeating code...
class PropertyView(SeachPropertyMixin,DetailView):
    template_name = 'properties/view.html'
    context_object_name = 'house'
    ...
    queryset = HouseModel.objects.select_related(...).prefetch_related(...).filter(flag_active=True, flag_status='a')

, ( GET, , GET):

# Search results should return a ListView, here is how we implement it:
class PropertySearchResultView(ListView):
    template_name = "properties/propertysearchresults.html"
    context_object_name = 'houses'
    paginate_by = 6
    queryset = HouseModel.objects.select_related(...).prefetch_related(...).order_by('-sale_price').filter(flag_active=True, flag_status='a')

    def get_queryset(self):
        qs = super(PropertySearchResultView,self).get_queryset()
        property_type = self.request.GET.get('property_type')
        location = self.request.GET.get('location')
        '''
        Start Chaining the filters based on the input, this way if the user has not 
        selected a filter it wont be used.
        '''
        if property_type != '' and property_type is not None:
            qs = qs.filter(housetype=property_type)
        if location != '' and location is not None:
            qs = qs.filter(location=location)
        return qs

    def get_context_data(self, **kwargs):
        context = super(PropertySearchResultView, self).get_context_data()
        ''' 
        Add the current request to the context 
        '''
        context['current_request'] = self.request.META['QUERY_STRING']
        return context
+3

. , ModelChoiceField, . ChoiceField. , "Any". "if" :

 if locality != 'Any Locality':
    qs = qs.filter(locality=locality)
if property_type != 'Any Type':
    qs = qs.filter(property_type=property_type)
if int(price_min) != 0:
    qs = qs.filter(price__gte=price_min)
if int(price_max) != 0:
    qs = qs.filter(price__lte=price_max)   
if bedrooms != 'Any Number':
    qs = qs.filter(bedrooms=bedrooms)

....

, . , . , ...

django. , , "" , , . .

+1
source

Source: https://habr.com/ru/post/1527472/


All Articles