1

First time using django-filter, so I might be using it wrong.

I'm basically trying to mimic Django Admin filtering, using a generic FilterView, setting filterser_class and adding paginate_by

filters.py

class ProductFilter(django_filters.FilterSet):
    name = django_filters.CharFilter(lookup_expr='icontains', label='Filter by Title')

    categories = django_filters.AllValuesFilter(
        field_name='categories__name',
        label="Filter by Category",
        widget=django_filters.widgets.LinkWidget(attrs={'class': 'list-menu'}),
    )

    brand = django_filters.AllValuesFilter(
        field_name='brand__short_name',
        label="Filter by Brand",
        widget=django_filters.widgets.LinkWidget(attrs={'class': 'list-menu'}),
    )

    class Meta:
        model = Product
        fields = ['categories', 'brand', 'name']

views.py

class ProductFilterView(FilterView):
    filterset_class = ProductFilter
    paginate_by = 20

product_filter.html

<section class="section-content padding-y">
    <div class="container">
        <div class="row">
            <aside class="col-md-3">
                <div class="card">

                    <form method="get">
                        {% csrf_token %}

                        {% for field in filter.form.visible_fields %}
                            <article class="filter-group">
                                <header class="card-header">
                                    <a href="#" data-toggle="collapse" data-target="#collapse_1" aria-expanded="true" class="">
                                        <i class="icon-control fa fa-chevron-down"></i>
                                        <h6 class="title">{{ field.label_tag }}</h6>
                                    </a>
                                </header>
                                <div class="filter-content collapse show" id="collapse_1">
                                    <div class="card-body">
                                        {{ field }}
                                    </div> <!-- card-body.// -->
                                </div>
                            </article> <!-- filter-group  .// -->
                        {% endfor %}

                        <input type="submit" class="btn btn-block btn-primary" value="Filter"/>
                    </form>

                </div> <!-- card.// -->

            </aside> <!-- col.// -->
            <main class="col-md-9">

                <header class="border-bottom mb-4 pb-3">
                    <div class="form-inline">
                        <span class="mr-md-auto">{{ filter.qs | length }} products found </span>

                    </div>
                </header><!-- sect-heading -->

                <div class="row">

                    {% for obj in page_obj %}
                    <div class="col-md-4">
                        <figure class="card card-product-grid">
                            <div class="img-wrap">

                                <img src="/media/{{ obj.productimage_set.first.image|default:'products/missing.png' }}">

                            </div> <!-- img-wrap.// -->
                            <figcaption class="info-wrap">
                                <div class="fix-height">
                                    <a href="./product-detail.html" class="title">{{ obj.name }}</a>
                                    <div class="price-wrap mt-2">
                                        <span class="price">$ {{ obj.price }}</span>
                                        <!--<del class="price-old">$1980</del>-->
                                    </div>
                                </div>
                                
                                <a href="#" class="btn btn-block btn-primary">Add to cart</a>
                            </figcaption>
                        </figure>
                    </div> <!-- col.// -->
                    {% endfor %}

                </div> <!-- row end.// -->

                <nav class="mt-4" aria-label="Page navigation">
                    <ul class="pagination">
                        {% if page_obj.has_previous %}
                            <li class="page-item"><a class="page-link" href="?page=1">First</a></li>
                            <li class="page-item"><a class="page-link" href="?page={{ page_obj.previous_page_number }}">Previous</a></li>
                        {% else %}
                            <li class="page-item disabled"><a class="page-link" href="#">First</a></li>
                            <li class="page-item disabled"><a class="page-link" href="#">Previous</a></li>
                        {% endif %}

                        {% for page in page_obj.paginator.page_range %}
                            {% ifequal page page_obj.number %}
                            <li class="page-item active"><a class="page-link">{{ page }}</a></li>
                            {% else %}
                            <li class="page-item"><a class="page-link" href="?page={{ page }}">{{ page }}</a></li>
                            {% endifequal %}
                        {% endfor %}

                        {% if page_obj.has_next %}
                            <li class="page-item"><a class="page-link" href="?page={{ page_obj.next_page_number }}">Next</a></li>
                            <li class="page-item"><a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">Last</a></li>
                        {% else %}
                            <li class="page-item disabled"><a class="page-link" href="#">Next</a></li>
                            <li class="page-item disabled"><a class="page-link" href="#">Last</a></li>
                        {% endif %}
                    </ul>
                </nav>

            </main> <!-- col.// -->

        </div>

    </div> <!-- container .//  -->
</section>

It almost works as intended.

But those pagination urls will reset any filtering.

I'm considering using {{ request.GET.param1 }} to rebuild all the filters, but it doesn't feel like the right way to solve this.

I've tried a solution using context processors, as described by José L. Patiño here:

How to paginate Django with other get variables?

But it leads to another problem: it's possible to reapply filtering after advancing some pages, and it results in invalid pages.

Any suggestions?

0 Answers0