Displaying Page Numbers with django-tables2 - python

I'm currently displaying a dataset using django-tables2.
The docs make no mention of this in particular, so I'm guessing this'll take probably some table overriding - but, I'm hopeful someone out there has already accomplished this.
How can I render page numbers using django-tables2 below my table? What I'd like to be able to display is a horizontal list of page numbers that the user can click.
Thanks in advance.

you need to create a custom page rendering template - you don't need to override any classses.
To do that, start by copying the file
PYTHON\Lib\site-packages\django_tables2\templates\django_tables2\table.html
to the templates directory inside your django application and rename it to mytable.html or whatever else you like.
Now, you need to change the pagination block of that file. There are many ways to do what you like, but a simple way is to add the following lines inside the pagination block (you may remove or keep the other things that are there depending on your specific needs):
{% block pagination.allpages %}
{% for p in table.paginator.page_range %}
{{ p }}
{% endfor %}
{% endblock pagination.allpages %}
Finally, to use your template, just pass your custom template name to the render_table command:
{% load render_table from django_tables2 %}
...
{% render_table table "mytable.html" %}
This is very simple and will give you trouble if you have many pages (so you have to use some ifs to check the number of pages through the table.paginator.num_pages variable). Also, you may highlight the current page and disable the link by using the table.page.number variable.
The above are left as an excersise to the reader :)

Improving on #Serafeim answer (or solving the exercise he left): Here is a pagination block which, using only Django template syntax, renders page numbers that:
are enclosed in a <ul> HTML block, whith CSS classes that "play well" with Bootstrap;
if there are more than 8 pages, at most 3 pages below and above current page are shown;
first and last pages are always shown, with ellipsis between them and the start or end of the range (if needed).
{% with current_page=table.page.number page_count=table.paginator.num_pages rows_per_page=table.page.object_list|length total_rows=table.page.paginator.count %}
{% block pagination %}
<ul class="pagination">
{% block pagination.allpages %}
<li class="current">
{% blocktrans %}Page {% endblocktrans %}
</li>
{% for page in table.paginator.page_range %}
{% with range_start=current_page|add:"-3" range_end=current_page|add:"3" page_count_minus_5=page_count|add:"-5" page_count_minus_1=page_count|add:"-1" %}
{% if page == current_page %}
<li class="active">
<span>{{ page }}</span>
</li>
{% elif page == 1 or page >= range_start and page <= range_end or page == page_count %}
<li class="next">
{{ page }}
</li>
{% endif %}
{% if page == 1 and current_page > 5 or page == page_count_minus_1 and current_page <= page_count_minus_5 %}
<li class="current">...</li>
{% endif %}
{% endwith %}
{% endfor %}
{% endblock pagination.allpages %}
{% block pagination.cardinality %}
<li class="cardinality">
{% if total_rows != rows_per_page %}{% blocktrans %}
{{ rows_per_page }} of {{ total_rows }}{% endblocktrans %}
{% else %}
{{ total_rows }}
{% endif %}
{% if total_rows == 1 %}
{{ table.data.verbose_name }}
{% else %}
{{ table.data.verbose_name_plural }}
{% endif %}
</li>
{% endblock pagination.cardinality %}
</ul>
{% endblock pagination %}
{% endwith %}

Pagination is introduced in version# >= 2.0.0
https://django-tables2.readthedocs.io/en/latest/pages/CHANGELOG.html
Simply add following code in settings.py. Pagination with number will be rendered with bootstap 4 style. Make sure you have bootstrap 4 reference in html template.
DJANGO_TABLES2_TEMPLATE = 'django_tables2/bootstrap4.html'
And check out more styles in documentation.
https://django-tables2.readthedocs.io/en/latest/pages/custom-rendering.html#available-templates

Related

How do i use the less than or greater than signs inside html in python django

Hi am struggling using the greater than sign inside the html template. am using python 3.7.2 and django 1.8.6
I cant execute this code here gives an error
{% extends "base.html" %}
{% block Content %}
<h1>Tags</h1>
{% for instance in object_list %}
<li><a href='{{ instance.get_absolute_url }}'>{{ instance.title }}</a> ({{ instance.products.count }} product{% if instance.products.count > 1 %}s{% endif %})</li>
{% empty %}
<li>No Tags yet.</li>
{% endfor %}
</ul>
{% endblock %}
So the > 1 is the problem here
help out

Overring menu blocks in Django DTL?

I got a navbar that will have four links,
{% block navbar %}
<div id="navbar">
Link 1
Link 2
Link 3
Link 4
</div>
{% endblock %}
A class='current' will define the current active page like
<a href="" class='current'>Link 4</a>
My question, is overriding the block navbar on each of the 4 links the best way to do it in Django template language so that each link will have a corresponding class 'current'?
There are many ways to solve this, the right one depends on your exact project. This being said, the simplest solution that could possibly work is to use the {% with %} tag and {{ block.super }}, ie:
In your base template:
{% block navbar %}
<div id="navbar">
Link 1
Link 2
Link 3
Link 4
</div>
{% endblock %}
And then in the template for the "Link1" page:
{% block navbar %}
{% with current="link1" %}
{{ block.super }}
{% endwith %}
{% endblock %}
etc...

Simplifying the compound extends

On my homepage, I would like to use other pages I have defined as sections. After my navigation, I have a portion for news and team members that run as stand alone pages on my site. It looks something like this:
Header
Nav
<div class="content">
{% include 'news.html' %}
{% include 'officers.html' %}
</div>
Footer
So my news has some basic html but in order not to clone my headers and nav I have to add this line:
{% if page_data.current_page == 'news' %} {% extends "base.html" %} {% endif %}
Is there a way to simplify this statement?
An alternative way to deal with the issue is to move the body of news.html into a partial, for example partials/news.html and then include it in both your home page and in the news page itself:
{# home.html #}
Header
Nav
<div class="content">
{% include 'partials/news.html' %}
{% include 'officers.html' %}
</div>
Footer
and then in news.html:
{% extends "base.html" %}
{% block where_news_belongs %}
{{ super() }} {# if we need to include the contents of the block #}
{% include 'partials/news.html %}
{% endblock where_news_belongs %}

Django {% blocktrans %}: How to handle pluralization inside a for loop?

I have the following loop in my Django template:
{% for item in state.list %}
<div> HTML (CUSTOMERS BY STATE) </div>
<!-- print sum of customers at bottom of list -->
{% if forloop.last %}
<h4>{{ forloop.counter }} Valued Customers</h4>
{% endif %}
{% endfor %}
Obviously, if I end up with only one customer, I'd like to print singular "Valued Customer"
According to Django's docs, one should use blocktrans. Tried the following, a few flavors of nesting:
{% blocktrans count %}
{% if forloop.last %}
<h4>
{{ forloop.counter }}
Valued Customer
{% plural %}
Valued Customers
</h4>
{% endif %}
{% endblocktrans %}
Keep getting TemplateSyntaxError: Invalid block tag: 'blocktrans', expected 'empty' or 'endfor'
Is there no way to combine with another loop? Any ideas how to solve? Thanks!
Here is the working code, thanks to alko:
{% load i18n %}
<!-- ... -->
{% if forloop.last %}
<h4>
{{ forloop.counter }}
{% blocktrans count count=forloop.counter %}
Valued Customer
{% plural %}
Valued Customers
{% endblocktrans %}
</h4>
{% endif %}
Probably, you forgot to load translation tags. Add following line at the top of your template:
{% load i18n %}
After you fix that, note that for a blocktrans tag after count a variable, whose value will serve for plural detection, should be specified, so you probably need something like
{% blocktrans count count=forloop.counter %}
To pluralize use this:
Customer{{ forloop.counter|pluralize }}

Querying for specific articles (via tag/category) in Pelican themes

Is it possible to set query parameters via jinja in Pelican template files?
index.html
{% if articles %}
{% for article in articles_page.object_list if article.category == 'article' %}
#stuff
{% endfor %}
{% endif %}
This will return articles in the article category, but only if they happen to be in the articles already queried for. The desirable setup would be to grab x articles in y category (or with y tag) - is that possible?
This code snippet works for me to bring back a list of all articles matching a tag:
{% block content %}
<ul>
{% for article in articles if FAVORITES_TAG in article.tags %}
{% if loop.index <= FAVORITES_COUNT %}
<li>{{ article.title }}</li>
{% endif %}
{% endfor %}
</ul>
{% endblock %}
I set the FAVORITES_TAG and FAVORITES_COUNT variables in the config. I hope that helps.
I ran into the same problem, and found a solution
{% if articles %}
{% for article in articles_page.object_list if article.category.name == 'article' %}
#stuff
{% endfor %}
{% endif %}

Categories

Resources