Use django-pagination to create a refl = next / prev link

I use django-pagination to paginate pages. It works great, but I would like to configure

<link rel="prev" href="http://www.example.com/foo/?page=1" /> <link rel="next" href="http://www.example.com/foo/?page=3" /> 

in <head> , for example, recommended by Google .

However, I did not find a way to do this (without additional requests, at least). At first I tried to edit pagination/templates/pagination.html with something like this

 {% block extra_head %} <link rel=... ... /> {% endblock %} 

Which, of course, did not work (pagination.html is included with the {% paginate %} tag, it does not extend my layout.html ). Then I tried to change my template for / foo / view to something like this (adding {% block extra_head %} ):

 {# foo.html #} {% extends "layout.html" %} {% block content %} {% load pagination_tags %} {% autopaginate object_list %} {% paginate %} {% for obj in object_list %} {{ obj }} {% endfor %} {% paginate %} {% endblock %} {% block extra_head %} <link rel="prev" href="?page={{ page_obj.previous_page_number }}"/> {% endblock %} 

But this will not work either, since the page_obj variable is only available in the {% block content %} . A may cause

 {% autopaginate object_list %} 

in the extra_head block, but that would mean an extra hit in db (and possibly other side effects that I don't know about). Is there an elegant way to solve this problem, ideally, as dry as possible?

Edit: I am using django 1.2.

+4
source share
2 answers

You can do {% autopaginate %} in a higher-level block, then paginated objects will be available in the sub-blocks. If you do not have a higher-level block, this can be done in the basic template:

 {% block root %} ... {% endblock %} 

And in the extended template:

 {% extends "base.html" %} {% load pagination_tags %} {% block root %} {% autopaginate objects 10 %} {{ block.super }} {% endblock %} <!-- the rest of your code --> 

Now, to get another paginator rendering in your head, you can use the with tag:

 {% with we_are_in_head=1 %} {% paginate %} {% endwith %} 

And redefine templates / pagination / pagination.html with something like this:

 {% if we_are_in_head %} # Your links to next and prev only {% else %} # original code {% endif %} 

Moral

This is not elegant, and the reason is that pagination must be implemented in view . Templates are for rendering only, template tags. The markup makes additional sql queries, it also parses the arguments from the query, the template is absolutely the wrong place for this code, so workarounds must be invented. These workarounds can break the next release of django, they are also subtle and can be accidentally broken by another developer.

+2
source

We can call autopaginate in the form and then use {% paginate %} as usual. Here is the recipe if someone else is faced with the described problem:

 from pagination.templatetags.pagination_tags import AutoPaginateNode def autopaginate(request, context, queryset_var, paginate_by): """ It allows us to use paginated objects in different template blocks """ autopagination = AutoPaginateNode(queryset_var, paginate_by) # Inject a request - it required by `autopagination` function context['request'] = request autopagination.render(context) 
0
source

Source: https://habr.com/ru/post/1381258/


All Articles