Flexible Django Filter (django-filter package)

64 Views Asked by At

I'm currently implementing some filters and I'm facing multiple problems. First of all my checkbox works when clicking on the brand title, not the actual: enter image description here

this is my .html code:

<form method="get">
    <div class="toggle-list product-categories">
        <h6 class="title">Sorteer</h6>
        <div class="shop-submenu">
            <ul>
                {{ filter.form.order_by }}
            </ul>
        </div>
    </div>
    <div class="toggle-list product-categories">
        <h6 class="title">Merk(en)</h6>
        <div class="shop-submenu">
            <ul>
            {% for f in filter.form.brand %}
                <li>
                   <input type="checkbox" name="brand" id="brand">
                   <label for="brand">{{ f }}</label>
                </li>
            {% endfor %}
            </ul>
        </div>
    </div>
    <input type="submit" value="Filter">
</form>

my filter in filters.py:

class SortFilter(django_filters.FilterSet):
    ORDER_BY_CHOICES = (
        ('-discount_sort', 'Hoogste korting'),
        ('-new_price', 'Hoogste prijs'),
        ('new_price', 'Laagste prijs'),
    )
    order_by = django_filters.ChoiceFilter(label='Sorteer op', choices=ORDER_BY_CHOICES, method='filter_by_order',
                                           empty_label=None)
    brand = django_filters.ModelMultipleChoiceFilter(queryset=Product.objects
                                                     .order_by('brand')
                                                     .filter(categorie='eiwitten')
                                                     .values_list('brand', flat=True).distinct()
                                                     , widget=forms.CheckboxSelectMultiple, required=False)

    class Meta:
        model = Product
        fields = ['brand']

    def filter_by_order(self, queryset, name, value):
        return queryset.order_by(value)

view function for this certain page:

def eiwit(request):
    # filter alleen eiwitproducten
    eiwit_list = ['eiwitten']
    eiwit_filter = Q()
    for item in eiwit_list:
        eiwit_filter = eiwit_filter | Q(categorie=item)

    products = models.Product.objects.filter(eiwit_filter)
    product_amount = len(products)

    # sorteer filter
    filtered = SortFilter(
        request.GET,
        queryset=products
    )

    # paginator
    paginator = Paginator(filtered.qs, 12)
    page = request.GET.get('page')
    try:
        response = paginator.page(page)
    except PageNotAnInteger:
        response = paginator.page(1)
    except EmptyPage:
        response = paginator.page(paginator.num_pages)
    product_front_end = {
        'final_products': response,
        'filter': filtered,
        'count': product_amount,
    }
    return render(request, 'producten/eiwit.html', product_front_end)

Second of all, I would like the filter to be more generic. As in all categories have different amount of brands. As you can see I currently create options by selecting all the 'brand' values within the 'eiwitten' categorie (in filters.py). Is there a way to call the filter in views.py with a variable (like 'eiwittien'). Which then will be used to adjust the filter in filter.py according to the page it is on? This way I have a dynamic filter for all categories.

1

There are 1 best solutions below

3
On

This might help with some of your issues. Your input tag is missing information on the name/id fields. You should be able to populate those by adding template tags to fill the values.

<input type="checkbox" id="BSN" name="BSN"> <label for="BSN">BSN</label>