Template rendering is wrong, category shows 2 times - python

So I am trying to render my models in a template but just one tiny thing shows more times than I expect. I just want category name to show one time for many lectures. I just cant figure where to modify the template code.
<ul>
{% for a in categories %}
{% for c in lectures %}
{% if a == c.course_category %}
<li><strong>{{ a.course_category }}</strong></li>
{% endif %}
{% if a == c.course_category %}
<li>{{ c.lecture_title }}</li>
<li>{{ c.content }}</li>
{% if c.link %}
<li>{{ c.link }}</li>
{% endif %}
{% if c.file %}
<li><a href='{{ MEDIA_URL }}{{ c.file.url }}'>download</a></li>
{% endif %}
{% endif %}
{% endfor %}
<hr/>
{% endfor %}
</ul>

You should move the {{ a.course_category }} out of the inner loop, so that you only display it once for each category.
{% for a in categories %}
<li><strong>{{ a.course_category }}</strong></li>
{% for c in lectures %}
<li>{{ lecture.lecture_title }}</li>
{% endfor %}
{% endfor %}
However, it's inefficient to loop through every lecture for every category. Depending on your models, you should be able to do something like:
{% for category in categories %}
<li><strong>{{ category.course_category }}</strong></li>
{% for lecture in category.lecture_set.all %}
<li>{{ lecture.lecture_title }}</li>
{% endfor %}
{% endfor %}
Or you might be able to loop through the lectures, and use the {% ifchanged %} tag to display the categories.
{% for lecture in lectures %}
{% ifchanged lecture.course_category %}
<li><strong>{{ lecture.course_category }}</strong></li>
{% endifchanged %}
<li>{{ lecture.lecture_title }}</li>
{% endfor %}

Related

Reverse for 'surveydetails' not found. 'surveydetails' is not a valid view function or pattern name

I've been stuck on this for a while, can't seem to fix the error. I've checked the code a hundred times but obviously there is something I'm missing. I have installed my app also.
Can anybody see what I'm missing?
views.py
def survey_details(request, id=None):
context = {}
surveys = Survey.objects.get(id=id)
context['survey'] = survey
return render(request, 'surveydetails.html', context)
feedback.urls.py
path('details/<int:id>', views.survey_details, name="surveydetails"),
surveys.html
{% extends 'main.html' %}
{% block content%}
<h1>Surveys</h1>
<h2>list of {{title}} </h2>
{% if surveys %}
<ul>
{% for survey in surveys %}
<li>
{{ survey.title }}
</li>
{% endfor %}
</ul>
{% else %}
<p>There are no surveys.</p>
{% endif %}
{% endblock %}
surveydetails.html
{% extends 'main.html' %}
{% block content%}
<h1>Surveys</h1>
<h2>Detail page</h2>
<h3>{{question.title}}</h3>
<p>Details page of {{question.title}}</p>
{% endblock %}
Here you are not passing the survey id.
{% for survey in surveys %}
<li>
{{ survey.title }}
</li>
{% endfor %}

Shorten the construction

The challenge is to reduce the construction and, if possible, speed up the processing of the code.
{% for tp1 in test.tab_tp1s %}
{{ tp1.name }}
{% endfor %}
{% for tp2 in test.tab_tp2s %}
{{ tp2.name }}
{% endfor %}
{% for tp3 in test.tab_tp3s %}
{{ tp3.name }}
{% endfor %}
{% for tab in test %}
{% for tp in test[tab]
{{ tp.name }}
{% endfor %}
{% endfor %}
Maybe, it's hard to tell because we don't know what is stored in test, I'm assuming test is a dictionary holding 3 keys which each hold a sub key called name?

Rendering Django template from withing template

So, I have a number of objects I wish to render in a loop. I.E. Render each of the 5 latest posts on the home page. Each of these posts will be displayed differently whether or not the user is logged in.
I have a question: How would I go about making this distinction? I imagine having a template like this
{% if user.is_logged_in %}
{% for post in latest_posts %}
post.render_long_form
{% endfor %}
{% else %}
{% for post in latest_posts %}
post.render_short_form
{% endfor %}
{% endif %}
How can I make the functions render_short_form and render_long_form return the appropriate HTML snippits? I would like them to call other templates for rendering under the hood.
Thanks!
Why don't not use {% include %} tag?
{% if user.is_logged_in %}
{% for post in latest_posts %}
{% include 'long_form.html' %}
{% endfor %}
{% else %}
{% for post in latest_posts %}
{% include 'short_form.html' %}
{% endfor %}
{% endif %}
Or, more DRY version:
{% for post in latest_posts %}
{% if user.is_logged_in %}
{% include 'long_form.html' %}
{% else %}
{% include 'short_form.html' %}
{% endif %}
{% endfor %}

Error in the template with Django : can I make arithmetic in if statement

I would like to make a pagination with Bootstrap : a new page every 10 new field in data.
file.html
{% for d in data %}
{% if forloop.first %}
<ul class="pagination">
{% endif %}
{% if (forloop.counter % 10) == 0 %}
<li>{{ forloop.counter % 10 }}</li>
{% endif %}
{% if forloop.last %}
</ul>
{% endif %}
{% endfor %}
output I would like that => Bootstrap pagination
But Django give me an error for this :
{% if (forloop.counter % 10) == 0 %}
TemplateSyntaxError :/
I don't know how to do except create my own filter or add a filter, but i would like to know first if i can do in the template first.
PS: I use Django 1.5 and I can't upgrade it.
Edit:
Finally I use this condition:
{% if forloop.counter|divisibleby:'10' and forloop.counter|divisibleby:'5' and forloop.counter|divisibleby:'2' %}
Like that I know when I have a 10 multiple.
The modulus (%) operator is not available in django templates. However, you can use the divisibleby (https://docs.djangoproject.com/en/1.5/ref/templates/builtins/#divisibleby) template filter, something like
{% if forloop.counter|divisibleby:"2" %}
Use the paginator, your QuerySet are not evaluated for the hole table, just the number you need to build the page, and it offers properties that you can use in the template like (page_range, next_page_number, has_next, etc.)
here is the code withe BootStrap 2 and django.core.paginator:
<div class="pagination pagination-centered">
<ul>
{% if MYDATAENTIRES.has_previous %}
<li>
{% trans "Précédent" %}
</li>
{% endif %}
{% for i in MYDATAENTIRES.paginator.page_range %}
<li {% ifequal MYDATAENTIRES.number i %} {{ 'class="disabled"' }} {% endifequal %}>
<a href="?page={{ i }}">
{{ i }}
</a>
</li>
{% endfor %}
{% if MYDATAENTIRES.has_next %}
<li>
{% trans "Suivant" %}
</li>
{% endif %}
</ul>
</div>

Getting a list of errors in a Django form

I'm trying to create a form in Django. That works and all, but I want all the errors to be at the top of the form, not next to each field that has the error. I tried looping over form.errors, but it only showed the name of the field that had an error, not an error message such as "Name is required."
This is pretty much what I'd like to be able to use at the top of the form:
{% if form.??? %}
<ul class="errorlist">
{% for error in form.??? %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
What would I use for ??? there? It's not errors; that just outputs the names of the fields.
form.errors is a dictionary. When you do {% for error in form.errors %} error corresponds to the key.
Instead try
{% for field, errors in form.errors.items %}
{% for error in errors %}
...
Etc.
Dannys's answer is not a good idea. You could get a ValueError.
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
{{field.label}}: {{ error|escape }}
{% endfor %}
{% endfor %}
{% endif %}
If you want something simple with a condition take this way :
{% if form.errors %}
<ul>
{% for error in form.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
If you want more info and see the name and the error of the field, do this:
{% if form.errors %}
<ul>
{% for key,value in form.errors.items %}
<li>{{ key|escape }} : {{ value|escape }}</li>
{% endfor %}
</ul>
{% endif %}
If you want to understant form.errors is a big dictionary.
You can use this code:
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
this add https://docs.djangoproject.com/en/3.0/ref/forms/api/#django.forms.Form.non_field_error

Categories