Dinh Truong Anh Phuong
Dinh Truong Anh Phuong

Reputation: 137

Pagination after filtering in django

I have an issue when trying to use pagination after filtering. I make a search form in forms. In the first page, after searching the app show all contracts with conditions, however when I click page 2, it refreshes and shows other results. If I rewrite in search form, it will show the others result in page 2 in my form.py

class ContractSearchForm(forms.ModelForm):
    use_required_attribute = False
    export_to_CSV = forms.BooleanField(required=False)
    class Meta:
        model = Contracts
        fields = ["contract","name"]

in my view.py

def list_contract(request):
    header= "LIST OF CONTRACT"
    form = ContractSearchForm(request.POST or None)

    queryset =Contracts.objects.all()
    
    #pagination
    paginate_by = 10
    paginate_by = request.GET.get('paginate_by', paginate_by) or 10
    user_list = queryset
    
    paginator = Paginator(user_list, paginate_by)
    page = request.GET.get('page',1)
    
    try:
        queryset = paginator.page(page)
    except PageNotAnInteger:
        users = paginator.page(1)
    except EmptyPage:
        users = paginator.page(paginator.num_pages)
    context = {
        "form":form,
        "header": header,
        "queryset": queryset1,
        'paginate_by':paginate_by,
    }
    if request.method == 'POST':
        #Tạo queryset sang filter
        queryset2 = Contracts.objects.filter(contract__icontains=form['contract'].value(),
                                    name__icontains=form['name'].value().upper()
                                    )
        #pagination when search
        paginate_by = 10
        paginate_by = request.GET.get('paginate_by', paginate_by) or 10
        user_list = queryset
        
        paginator = Paginator(user_list, paginate_by)
        page = request.GET.get('page',1)
        
        try:
            queryset = paginator.page(page)
        except PageNotAnInteger:
            users = paginator.page(1)
        except EmptyPage:
            users = paginator.page(paginator.num_pages)
        context = {
            "form":form,
            "header": header,
            "queryset": queryset,
            'paginate_by':paginate_by,
        }

    return render (request, "customer1.html",context)

in customer1.html

{% if queryset.has_previous %}
                      <a href="?{% param_replace page=1 %}">First</a>
                      {% if queryset.previous_page_number != 1 %}
                        <a href="?{% param_replace page=queryset.previous_page_number %}">Previous</a>
                      {% endif %}
                    {% endif %}

                    Page {{ queryset.number }} of {{ queryset.paginator.num_pages }}

                    {% if queryset.has_next %}
                      {% if queryset.next_page_number != queryset.paginator.num_pages %}
                        <a href="?{% param_replace page=queryset.next_page_number %}">Next</a>
                      {% endif %}
                      <a href="?{% param_replace page=paginator.num_pages %}">Last</a>
                    {% endif %}

my ulr.py

 urlpatterns = [
        path('admin/', admin.site.urls),
        path('demo',views.showDemoPage),
        path('', include('test_upload_filter.urls')),
        path('add_items/', views.add_items, name='add_items'),
        path('contract_detail/<str:contract_id>/', views.contract_detail, name="contract_detail"),

in my app url.py

app_name='example_app'
urlpatterns = [
    path("customer1/",page,name="list_contract")
]

I updated my code, I use template tag my_tags.py

@register.simple_tag(takes_context=True)
def param_replace(context, **kwargs):

    d = context['request'].GET.copy()
    for k, v in kwargs.items():
        d[k] = v
    for k in [k for k, v in d.items() if not v]:
        del d[k]
    return d.urlencode()

I try use django-filter with paginations but django-filter cannot distinguish upper and lower case. My url browser is still the same after and before searching 127.0.0.1:8000/customer1 , in page 2 http://127.0.0.1:8000/customer1/?page=2 Thanks for your reading. Sorry because my code in view is too long because I have to rewrite two times pagination function.

Upvotes: 1

Views: 574

Answers (2)

Thomas Heaton
Thomas Heaton

Reputation: 21

I don't know if this helps. I had a similar problem and just adapted the pagination urls:

<div id="pagelinks">
    {% if ideas.has_previous %}
    <a class="infinite-more-link" href="{{ request.get_full_path }}&page={{ ideas.previous_page_number }}" style="float:left;">&lt;- Previous ideas<a>
    {% endif %}
    {% if ideas.has_next %}
        <a class="infinite-more-link" href="{{ request.get_full_path }}&page={{ ideas.next_page_number }}" style="float:right;">More ideas -&gt;</a>
    {% endif %}    
</div>

JavaScript: <script> function Waypoint(){ var infinite = new Waypoint.Infinite({ element: $('.infinite-container')[0] }); } </script>

Upvotes: 2

Reza GH
Reza GH

Reputation: 2102

use your own views.py

then you need to build a template tag in 'your_app_name/templatetags/my_tags.py' root like below code

my_tags.py

from django import template

register = template.Library()


@register.simple_tag(takes_context=True)
def param_replace(context, **kwargs):
    d = context['request'].GET.copy()
    for k, v in kwargs.items():
        d[k] = v
    for k in [k for k, v in d.items() if not v]:
        del d[k]
    return d.urlencode()

finally use that templatetag in in your template pagination:

html file

(don't forget to load your tag first)

notice where i'm using param_replace

{% load my_tags %}

.
.
.
.

<!-- Pagination -->
<nav aria-label="Page navigation">
    {% if queryset.has_other_pages %}
    <ul class="pagination justify-content-center">

        {% if queryset.has_previous %}
        <li class="page-item disabled">
            <a class="page-link page-link-prev" href="{% url 'url_app_name:current_path_url_name' %}?{% param_replace page=queryset.previous_page_number  %}" aria-label="Previous" tabindex="-1" aria-disabled="true">
                <span aria-hidden="true"><i class="icon-long-arrow-left"></i></span>Previous
            </a>
        </li>
        {% endif %}

        {% for i in queryset.paginator.page_range %}                    
            {% if queryset.number == i %}
            <li class="page-item active" aria-current="page"><a class="page-link" href="#">{{ i }}</a></li>
            {% else %}
            <li class="page-item"><a class="page-link" href="?{% param_replace page=i  %}">{{ i }}</a></li>
            {% endif %}
        {% endfor %}

        {% if queryset.has_next %}
        <li class="page-item">
            <a class="page-link page-link-next" href="{% url 'url_app_name:current_path_url_name' %}?{% param_replace page=queryset.next_page_number  %}" aria-label="Next">
                Next<span aria-hidden="true"><i class="icon-long-arrow-right"></i></span>
            </a>
        </li>
        {% endif %} 

    </ul>
    {% endif %}
</nav>
<!-- Pagination -->

.
.
.

let me know if this worked for you

i can give you full working code that i'm using for myself for multiple filtering with pagination that you want

sorry for bad EN (:

Upvotes: 0

Related Questions