This is python utility for Django that helps determine the page number on which a specific model instance appears within a paginated queryset or related object set. It also includes a Django templatetag for rendering HTMX + Bootstrap-compatible pagination with support for large page ranges and dynamic page loading.
Imagine you're working on a Django project where you want to highlight or scroll to a specific item on a paginated list — for example, highlighting a comment on a forum post. To do this, you need to calculate which page that comment appears on and then include that page number in the URL, like so:
localhost:8000/forum/posts/151/?comment=17&page=4
This allows you to directly link to the page where the target item exists.
Instead of manually figuring this out, use FlexPageResolver
or PageResolverModel
.
See Usage
.
pip install django-page-resolver
Then you have to pass django_page_resolver
to your INSTALLED_APPS
:
INSTALLED_APPS = [
...
'django_page_resolver',
...
]
Using of page-resolver to determine object's page location in paginated queryset.
There is a two ways to do so:
-
Using abstract model
PageResolverModel
:from django_page_resolver.models import PageResolverModel class Comment(PageResolverModel): ... # OR class Post(PageResolverModel): ...
And then you have next API:
comment = Comment.objects.get(pk=27) comment_page_number = comment.get_page_from_queryset(order_by='-relevancy_value', items_per_page=15) # comment_page_number -> return 3 # OR post = Post.objects.get(pk=120) comment_page_number_from_post = post.get_page_from_nested_object(target_child_instance=comment, order_by='-relevancy_value', items_per_page=15) # comment_page_number_from_post -> return 3
-
Using
page_resolver
class instance to do the same as was described above.from django_page_resolver.resolvers import page_resolver comment = Comment.objects.get(pk=27) comment_page_number = page_resolver.get_page_from_queryset( target_instance=comment, order_by='-relevancy_value', items_per_page=15 ) # comment_page_number -> return 3 # OR post = Post.objects.get(pk=120) comment_page_number_from_post = page_resolver.get_page_from_nested_object( parent_instance=post, target_child_instance=comment, order_by='-relevancy_value', items_per_page=15 ) # comment_page_number_from_post -> return 3
Parameters:
get_page_from_nested_object
:
parent_instance
: The parent model instance (e.g., Post). Required and uses only frompage_resolver
instance.target_child_instance
: The related model instance to locate (e.g., Comment). Required.siblings_qs
: Optional queryset to search in. If not provided, will use target_child_instance's model.related_name
: The related name on the parent that accesses the child objects (e.g., 'comments'). (By default takesverbose_name_plural
from the Model's meta.)order_by
: Field used to order the queryset. Default isNone
.items_per_page
: The pagination size (number of items per page). Required.
get_page_from_queryset
:
target_instance
: The instance whose page number we want to find. Required and uses only frompage_resolver
instance.queryset
: Optional queryset to search in. If not provided, will use target_instance's model. (By default takes default__class__.objects.all()
queryset from the Model)order_by
: Field to order the queryset by. Default isNone
.items_per_page
: Number of items per page for pagination. Required.
And then you have it!
Prerequisites:
If you've set up page_resolver logic, you can use additional template tags and JavaScript utilities to automatically scroll to a specific instance on the page.
The JavaScript reads URL parameters that contain the unique identifier of the instance to scroll to.
Example:
-
Load
page_resolvers
templatetags in your HTML:
{% load page_resolvers %}
-
Include the script and CSS styles in your HTML:
<script src="{% static 'resolvers/js/page_resolvers.js' %}"></script> <link type="text/css" href="{% static 'resolvers/css/page_resolvers.css' %}" rel="stylesheet">
-
Inside your {% for %} loop, register the object to be scrolled to:
{% register_scroll_obj_unique_pk instance_pk=comment.pk %}
(You can use another unique identifier, such as a UUID.)This will mark the object as a scroll target.
-
Finally, add this tag inside the class attribute of your main HTML element:
{% classes_by_lookup_url instance_pk=comment.pk url_lookup='comment' %}
(Or other unique identified like UUID)Like so:
<div class="container {% classes_by_lookup_url instance_pk=comment.pk url_lookup='comment' %}">...</div>
classes_by_lookup_url
takes the following arguments:instance_pk
: The unique ID of the instance (could be UUID or another PK), that the page should scroll to.url_lookup
: The name of the parameter in the URL. (Like/?comment=12&page=2
, whereurl_lookup
is acomment
parameter name.)
(See examples in /examples/templatetags/register_instance_scroll.html
within the library directory.)
Additionaly, you can have handsome dynamic HTMX+Bootstrap HTML paginator via templatetag!
Load page_resolvers
templatetags into your HTML:
{% load page_resolvers %}
Then just pass render_htmx_pagination
templatetag with htmx_target argument in your HTML code like so:
{% render_htmx_pagination "#comment-list-body-js" %}
Note: You need to add render_htmx_pagination
templatetag inside tag that has htmx_target selector which is you have specified.
This is required because of rerender the pagination block with objects list while htmx-request. See examples in examples
folder.
That will render default bootstrap pagination with HTMX and nice-UI large pages count support and i18n. You can also add some classes to every element in pagination:
{% render_bootstrap_pagination '#post-list-js' ul_class="some-outstanding-class" li_class="more-class" a_class="text-danger" %}
And this is what you get then:
You’re welcome to contribute to django-page-resolver by submitting pull requests, suggesting ideas, or helping improve the project in any way. Let’s make this library better together!