Control flow in Django template language - python

I have the following code, written inside a Django template.
{% if user.is_authenticated %}
<div style="float: right;">
{% for rel in RELATIONS %}
{% if rel.group_id == g.id %}
Unsubscribe
{% endif %}
{% else %}
Enrol
{% endfor %}
</div>
{% endif %}
The purpose of the code is to check if there is a match and then print out the unsubscribe tag. If there is not match print out the subscribe tag.
The reason I am having trouble doing this is because you in Django templates, I read that you can't have variables (i.e. a True or False).
UPDATE: (The question)
I want to only print out the Unsubscribe/subscribe button once. Print out the unsubscribe button only if there is a match inside the for loop. Otherwise print out the subscribe button if there is no match (i.e. no match at all for rel.group_id == g.id )
UPDATE 2:
While doing some research earlier I found this: https://code.djangoproject.com/ticket/3481
This might add some context to my problem.
Thank you for your help.

Seems like your if/else/endif are mixed up. Try
{% if user.is_authenticated %}
<div style="float: right;">
{% for rel in RELATIONS %}
{% if rel.group_id == g.id %}
Unsubscribe
{% else %}
Enrol
{% endif %}
{% endfor %}
</div>
{% endif %}
UPDATE
You want to check if g is in relations and make your decission based upon that.
The way I usually solve this is to create a function in my view that does this check and passes that allong to the view. Have a look here.

Related

How to catch an element from a for loop in Django template?

I'm looping through to different categories and rendering results (of its name and its associated pages). This code is rendering correctly.
{% for category in categories %}
<div class="row">
<div class="col-lg-4">
<h3>{{category.category_name}}</h3>
{% for page in category.page_set.all %}
<p><a href="{{page.get_absolute_url}}">{{page.page_title}}</p>
{% endfor %}
</div>
</div>
{% endfor %}
I'd like to catch an specific element inside the for loop (to be precise the 4th one in the forloop counter) and customize it (adding some html and text only to that one). I tried using the forloop.counter like this:
{% if forloop.counter == 4 %}
<!-- modified content -->
{% endif %}
But there isn't any results (not showing any changes). Is there any way to do this?
As per my understanding of your question. You can try it soo:
You can place this inside your for loop so that whenever you it iterates and by that you can use your if value to do some operations for specific value.
{% if some_variable == some_value %}
{{ do_something }}
{% endif %}

get_children not working. get_descendants does. But i can't use that

I am currently working on the navbar of a project with Django-cms. I am fairly new to this framework and language, so sorry if this is a stupid question.
This has double dropdowns, which respond to user changes in the Django-cms admin interface.
Which works. Sort of.
The problem is that get_children doesn't work (no errors or something, just not detecting children, and showing the 'should be dropdown button' as a non dropdown version), but get_descendants does. But if i use that the content of the second dropdown will be shown again in the first dropdown. So get_children will be perfect, as it will only show the direct descendants, instead of all.
{% load cms_tags menu_tags sekizai_tags staticfiles%}
{% load menu_tags %}
{% for child in children %}
<!--non dropdown 1-->
{% if child.is_leaf_node %}
<li>{{child.get_menu_title }}</li>
{% endif %}
<!--dropdown 1-->
{% if not child.is_leaf_node or child.ancestor %}
<div class="dropdown">
<li>{{child.get_menu_title }}<b class="caret"></b></li>
<!-- dropdown 1 content-->
{% if child.get_descendants %}
<div class="dropdown-content">
{% for kid in child.get_descendants %}
<!--non dropdown 2-->
{% if kid.is_leaf_node %}
<li>{{kid.get_menu_title }}</li>
{% endif %}
<!--dropdown 2 -->
{% if not child.is_leaf_node or child.ancestor %}
<li>
<a class="menu-has-sub">{{kid.get_menu_title }}<i class="fa fa-angle-down"></i></a>
<!-- dropdown 2 content-->
<ul class="sub-dropdown droppeddown">
{% for baby in kid.get_descendants %}
<li>{{baby.get_menu_title }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{% endif %}
{% endfor %}
So my question is: Why can't i use children
EDIT: *Why can't i use get_children. As in the function. No child labour here.
Nvm i fixed it! The syntax in this case should be children instead of get_children. which is funny because of that edit above.
Anyway, here's an example:
This doesn't work:
{% for kid in child.get_children %}
This does work:
{% for kid in child.children%}
hopefully this will help anyone else having this little struggle.

how to use name space instead of hard coded url in django templales for pagination

i am newbie in django,i have django templates where i have added the following code for pagination.here you can see that i have apply hard coded url for pagination.but i don't want to use hard coded url ,i want to use namespace instead of the hard coded url.how can i do this.
Template:
<span class="page-links">
{% if page_obj.has_previous %}
{% if query_string %}
previous
{% else %}
previous
{% endif %}
{% endif %}
</span>
my urls:
url(r'^(?P<chain_pk>[0-9]+)/full/combination/$',
CombinationSearchList.as_view(), name='dash_combination_search_list'),
Update
my django version is 1.6
<span class="page-links">
{% if page_obj.has_previous %}
{% if query_string %}
previous
{% else %}
previous
{% endif %}
{% endif %}
</span>
Please note that I have used point.id on the url to provide the value for the point.id in your hardcoded url. This can be any other variable, like object.pk or object.id or any other context variable. If this is not clear post again with the view code of the page and I can help.

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

How can I use break and continue in Django templates?

I want to put break and continue in my code, but it doesn't work in Django template. How can I use continue and break using Django template for loop. Here is an example:
{% for i in i_range %}
{% for frequency in patient_meds.frequency %}
{% ifequal frequency i %}
<td class="nopad"><input type="checkbox" name="frequency-1" value="{{ i }}" checked/> {{ i }} AM</td>
{{ forloop.parentloop|continue }} ////// It doesn't work
{ continue } ////// It also doesn't work
{% endifequal %}
{% endfor%}
<td class="nopad"><input type="checkbox" name="frequency-1" value="{{ i }}"/> {{ i }} AM</td>
{% endfor %}
Django doesn't support it naturally.
You can implement forloop|continue and forloop|break with custom filters.
http://djangosnippets.org/snippets/2093/
For-loops in Django templates are different from plain Python for-loops, so continue and break will not work in them. See for yourself in the Django docs, there are no break or continue template tags. Given the overall position of Keep-It-Simple-Stupid in Django template syntax, you will probably have to find another way to accomplish what you need.
For most of cases there is no need for custom templatetags, it's easy:
continue:
{% for each in iterable %}
{% if conditions_for_continue %}
<!-- continue -->
{% else %}
... code ..
{% endif %}
{% endfor %}
break use the same idea, but with the wider scope:
{% set stop_loop="" %}
{% for each in iterable %}
{% if stop_loop %}{% else %}
... code ..
under some condition {% set stop_loop="true" %}
... code ..
{% endif %}
{% endfor %}
if you accept iterating more than needed.
If you want a continue/break after certain conditions, I use the following Simple Tag as follows with "Vanilla" Django 3.2.5:
#register.simple_tag
def define(val=None):
return val
Then you can use it as any variable in the template
{% define True as continue %}
{% for u in queryset %}
{% if continue %}
{% if u.status.description == 'Passed' %}
<td>Passed</td>
{% define False as continue %}
{% endif %}
{% endif %}
{% endfor %}
Extremely useful for any type of variable you want to re-use on template without using with statements.

Categories

Resources