Django iterate queryset just n number of times in templates - python

My issue is quite simple. I am using Django taggit.
I want to iterate this only 2 times. Means to display only 4 tags in templates.
{% for tag in data.tags.all %}
{{tag}}
{% endfor %}
I have tried this, but it is not making any sense:
{% for tag in data.tags.all|ljust:"2" %}
{{tag}}
{% endfor %}
Can anyone suggest how can I achieve it?

You can make use of the |slice template filter [Django-doc]:
{% for tag in data.tags.all|slice:':2' %}
{{ tag }}
{% endfor %}

Related

django concat string with comma in template

I am newbie in django. How can I concat string in a for loop in django template
{% for lead in project.leaders %}
{% if forloop.counter == 1 %}
{% lead_member = lead.0 %}
{% else %}
{% lead_member = ','.lead.0 %}
{% endif %}
{{ lead_member }}
{% endfor %}
Finally my lead_member should be test1,test2,test3....
what is happening now (my current code)
{% for lead in project.leaders %}
{{ lead.0}}
{% endfor %}
and the output is test1test2test3.... but i want to make same as test1,test2,test3....
Try this. it works
{% for lead in project.leaders %}
{{ lead.0 }}{% if not forloop.last %}, {% endif %}
{% endfor %}
There's no need to assign anything, nor do you need that type of complexity by using assignment tags. To keep your templating stupid-simple, you could always do this in your view, or even at the model level:
# don't step on the `join` built-in
from django.template.defaultfilters import join as join_filter
class Project(models.Model):
#property
def leaders(self):
return join_filter(self.objects.values_list('some_field', flat=True), ', ')
Then all you have to do in the template is:
{{ project.leaders }}
It's hard to understand your question, but I hope i did it. There is a number of related questions such as String-concatination,
How to concatenate in django
It's possible to create first string, concatinate it with comma and new string for every iteration. You are also able to make smth like ','.join(list_of_strings) on your server side before rendering. You can also join your list in templating by {{ list|join:", " }}.

django template print out by filter id value

I want to print value by id in database,And don't know which keywords to find in Google.
in my views.py, I send transen = TransEn.objects.all() to template
and this will print all datas from database:
{% for words in transen %}
{{words.words|safe }}
{% endfor %}
But I want to print by the value of the id Like:
(Because they are words in English for translating website)
I don't know how to write this in template, please guide me, Thank you very much.
<div><span> TransEn.objects.filter(id='2') </span></div>
<div> TransEn.objects.filter(id='3') </div>
UPDATE:
I have found a method:
I can use if tag, but are there another ideas??
<div>
{% for words in transen %}
{% if words.id == 2 %}
{{ words.words|safe }}
{% endif %}
{% endfor %}
</div>
<div>
{% for words in transen %}
{% if words.id == 3 %}
{{ words.words|safe }}
{% endif %}
{% endfor %}
</div>
If you want to access each item in the QuerySet individually, by index, you should cast it to a list first. You should change your views.py to:
transen = list(TransEn.objects.all())
And then in your template you can access them by index like so:
<div><span> {{ transen.1.words }} </span></div>
<div> {{ transen.2.words }} </div>
A warning from the Django docuemtnation about casting a QuerySet to a list:
Be warned, though, that this could have a large memory overhead, because Django will load each element of the list into memory. In contrast, iterating over a QuerySet will take advantage of your database to load data and instantiate objects only as you need them.

How to use __repr__ method within django template?

For example, there is an object in a nested loop:
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
{% if field.is_hidden %} {{ field.field }} {% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endif %}
Now I want to check the class name and some information about field.field, so I use field.field.__repr__() to replace field.field.
However, the django template complains about it after the change:
Variables and attributes may not begin with underscores: 'field.field.__repr__'
Does anyone have idea about this? And is there any better way to debug for a variable in django template? (I tried {% debug %} but found it awful when I want to check a variable in a nested loop..)
{{ value|stringformat:'r' }}
uses the string % operator style formatting with the r format which uses repr()
You could easily write a template filter which allows you to do {{ var|asrepr }}. See the documentation, but it'll look something like this:
#register.filter
def asrepr(value):
return repr(value)

Displaying Page Numbers with django-tables2

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

Django query manytomanyfield in template

How can I query a manytomanyfield in a Django template?
For example, this if statement doesn't work (I know I can't call functions with arguments in Django templates), but this shows what I'd like to do:
template.html
{% for post in posts %}
{% if post.likes.filter(user=user) %}
You like this post
{% else %}
<a>Click here to like this post</a>
{% endif %}
{% endfor %}
models.py
class User(Model):
# fields
class Post(Model):
likes = ManyToManyField(User)
In order to do what you are looking for, you could do the following:
{% for post in posts %}
{% if user in post.likes.distinct %}
You like this post
{% else %}
<a>Click here to like this post</a>
{% endif %}
{% endfor %}
Alternatively, you could use Greg's approach. The advantage of his answer is that it would scale better when you get into very large datasets. This approach does not require you to write any custom filters.
It doesn't work because you appear to be writing python code in a template... you need to either run the loop in your view and pass a list of posts and their information to the template, or write a template filter that determines whether a certain user likes a post. For example:
from django import template
register = template.Library()
#register.filter
def is_liked_by(post, user):
return bool(post.likes.filter(user=user))
Then in your template:
{% for post in posts %}
{% if post|is_liked_by:request.user %}
You like this post
{% else %}
<a>Click here to like this post</a>
{% endif %}
{% endfor %}

Categories

Resources