Search code examples
djangodjango-viewsdjango-forms

Django generic List View with multiple query search


Hello I'm working with class based views in Django and I want to create a search form for users to find their own favourite products in my app with multiple filters and excludes but I couldn't do it. my code is here if anyone can modify it to make it right please help me out :

models.py

from django.db.models import models
from django.core.validators import RegexValidators


class Product(models.Model):
    num=RegexValidators(r'^[0-9a-zA-Z]*$')
    title = models.CharField(max_length=100)
    embed_id = models.CharField(max_length=15, validators=[num])
    description = models.TextField(null=True, blank=True)

forms.py

from django import forms


class ProductSearchForm(forms.Form):
    title = forms.CharField(required=False)
    embed_id = forms.CharField(required=False)
    description = forms.CharField(required=False)

views.py

from django.views.generic import ListView
from .models import Product
from .forms import ProductSearchForm


class ProductListView(ListView):
    model = Product
    form_class = ProductSearchForm
    template_name = 'pages/product/list_products.html'

    def get_queryset(self):
       queryset = super().get_queryset()
       form = self.form_class(self.request.GET)
       if form.is_valid():
           title = form.cleaned_data.get('title')
           embed_id = form.cleaned_data.get('embed_id')
           description = form.cleaned_data.get('description')
           if title:
              queryset = queryset.filter(title__icontains=title)
           if embed_id:
              queryset = queryset.filter(embed_id__icontains=embed_id)
           if description:
              queryset = queryset.filter(description__icontains=description)
           return queryset

   def get_context_data(self, [**kwargs):
      context = super().get_context_data(self, **kwargs):
      context['form'] = self.form_class(self.request.GET)
      return context

product_search.html

<form method="get" action="{% url 'product_list' %}">
{{ form.as_p }}
<input type="submit" value="Search">
</form>
{% if object_list %}
<ul>
{% for product in object_list %}
<li>{{ product.title }}</li>
{% endfor %}
</ul>
{% else %}
<p>No product found.</p>
{% endif %}

I know how to handle this in Function based views, but I want to create its generic.listview.


Solution

  • I tried using your code cannot run.

    Here is my way:

    views.py

    from django.views.generic import ListView
    from .models import Product
    from .forms import ProductSearchForm
    
    
    class ProductListView(ListView):
        model = Product
        form_class = ProductSearchForm
        template_name = 'product.html'
        context_object_name = 'products'
        
        def get_queryset(self):
            queryset = super().get_queryset()
            form = self.form_class(self.request.GET)
            if form.is_valid():
                title = form.cleaned_data.get('title')
                embed_id = form.cleaned_data.get('embed_id')
                description = form.cleaned_data.get('description')
                if title:
                    queryset = queryset.filter(title__icontains=title)
                if embed_id:
                    queryset = queryset.filter(embed_id__icontains=embed_id)
                if description:
                    queryset = queryset.filter(description__icontains=description)
            return queryset
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['form'] = self.form_class(self.request.GET)
            return context
    

    all data

    data

    search data

    results