Search code examples
djangodjango-modelsdjango-viewsdjango-filterdjango-template-filters

How to Check box filter In Django?


I'm using Django as backend, Postgres SQL as DB, and HTML, CSS, and Javascript as frontend. I am stuck in the filtering option, where the user selects check one brand and shows the selected brand list in the template. So basically like this:

enter image description here

I have multiple specifications for each category. Like Mobiles have:

  1. Brand
  2. RAM
  3. ROM etc.

Till now, I have done list filtering but I want check-box filtering.

The Codes goes here:

views.py

def product(request, data=None):
    product = Product.objects.all()

    if data == None:
        proc = Product.objects.filter(category = 1)
    elif data == 'OnePlus' or data == 'boAt' or data == 'Redmi' or data == 'realme':
        proc = Product.objects.filter(category = 1).filter(brand = data) 

    return render(request, 'list/processor.html', {'product': product, 'proc':proc,})

product.html

<ul class="list-group">
                <a style="text-decoration:none" href="{% url 'main:product' %}">
                    <li class="list-group-item d-flex justify-content-between align-items-center">
                        All
                    </li>
                </a>
                <a style="text-decoration:none" href="{% url 'main:productdata' 'OnePlus'%}">
                    <li class="list-group-item d-flex justify-content-between align-items-center">
                        OnePlus
                    </li>
                .......  
            </ul>

I have searched for Django-Filter but proper implementation of check-box filtering not there. How the Checkbox filtering will be done because this process takes too much time. Is there any easy way where all the particular columns get a filter, for ex. if brand name LG is repeated more than one time the query will filter those to one and append them to check-box filtering?


Solution

  • Based on your implementation of checkboxes being links, it makes most sense to do this filtering via get requests rather than URL parameters.

    For example;

        def product(request):
            brand = request.GET.get('brand')
    
            if brand:
                product = Product.objects.filter(category=1).filter(brand=brand)
            else:
                product = Product.objects.filter(category=1)
    
            products = Product.objects.all() 
        
            return render(
                request, 'list/processor.html',
                {'products': products, 'product': product,}
            )
    

    product.html

        <ul class="list-group">
                        <a style="text-decoration:none" href="{% url 'main:product' %}">
                            <li class="list-group-item d-flex justify-content-between align-items-center">
                                All
                            </li>
                        </a>
                        <a style="text-decoration:none" href="{% url 'main:productdata' %}?brand=OnePlus">
                            <li class="list-group-item d-flex justify-content-between align-items-center">
                                OnePlus
                            </li>
                        .......  
                    </ul>
    

    To use checkboxes, you'd need a form to handle the input by the user;

    <form action="{% url 'main:productdata' %}" method="get">
        <label for="oneplus">OnePlus: </label>
        <input id="oneplus" type="checkbox" name="oneplus">
        <input type="submit" value="OK">
    </form>
    
        def product(request):
            oneplus = request.GET.get('oneplus')
    
            if oneplus:
                product = Product.objects.filter(category=1).filter(brand__iexact=oneplus)
            else:
                product = Product.objects.filter(category=1)
    
            products = Product.objects.all() 
        
            return render(
                request, 'list/processor.html',
                {'products': products, 'product': product,}
            )
    

    If I were you, I'd also do this using a django form to make rendering it easier. The form might look something like this;

    class BrandForm(forms.Form):
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            brands = Product.objects.filter(category=1).values_list('brand', flat=True)
            for brand in brands:
                self.fields[f'{brand}'] = forms.BooleanField(label=f'{brand}')
    

    In your view you then need to create an instance of the form and pass it in the context.

    
            form = BrandForm()
            return render(
                request, 'list/processor.html',
                {'form': form, 'products': products, 'product': product}
            )
    

    And then render the form;

    <form action="{% url 'main:productdata' %}" method="get">
        {{ form.as_p }}
        <input type="submit" value="OK">
    </form>