Tree view in django template - python

I try to create simple TODOList app. Where you can create Project, then create tasks for project, subtasks for tasks and subtasks. I create a template to show task:
<li class='task'>
<div class="collapsible-header" id="task-name"> {{task.title}}</div>
<div class="collapsible-body" data-task-pk='{{task.pk}}' id="task-details">
{% include 'ProjectManager/views/control-block.html' %}
<p>{{task.description}}</p>
<ul class="collapsible popout" data-collapsible="expandable" id="subtasks">
{% for sub_task in task.subtasks.all %}
{% include "ProjectManager/views/task_view.html" with task=sub_task %}
{% endfor %}
</ul>
</div>
</li>
You can see i try to create a list of subtask, by using this template recursively, but I got an error:
'RecursionError' object has no attribute 'token'
I found some informations, that i should use variable to store template name, like this:
<li class='task'>
<div class="collapsible-header" id="task-name"> {{task.title}}</div>
<div class="collapsible-body" data-task-pk='{{task.pk}}' id="task-details">
{% include 'ProjectManager/views/control-block.html' %}
<p>{{task.description}}</p>
<ul class="collapsible popout" data-collapsible="expandable" id="subtasks">
{% for sub_task in task.subtasks.all %}
{% with node=sub_task template_name="ProjectManager/views/task_view.html" %}
{% include template_name with task=node%}
{% endwith %}
{% endfor %}
</ul>
</div>
</li>
I got an error:
maximum recursion depth exceeded
But at start I wrote wrong:
{% with node=**subtask** template_name="ProjectManager/views/task_view.html" %}
And template display list of subtasks with empty elements (without task.title and description).
Then I tried to put some if condition:
<li class='task'>
<div class="collapsible-header" id="task-name"> {{task.title}}</div>
<div class="collapsible-body" data-task-pk='{{task.pk}}' id="task-details">
{% include 'ProjectManager/views/control-block.html' %}
<p>{{task.description}}</p>
<ul class="collapsible popout" data-collapsible="expandable" id="subtasks">
{% if task.subtasks.all|length %}
{% for sub_task in task.subtasks.all %}
{% with node=sub_task template_name="ProjectManager/views/task_view.html" %}
{% include template_name with task=node%}
{% endwith %}
{% endfor %}
{% endif %}
</ul>
</div>
</li>
But I got new error:
maximum recursion depth exceeded while calling a Python object
How can I do this with Django templates?
Full traceback
In this way I show tasks list:
<div class="card-content">
<ul class="collapsible popout" data-collapsible="expandable" id="main-tasks">
{% for task in project.tasks.all %}
{% include 'ProjectManager/views/task_view.html' with task=task%}
{%endfor%}
</ul>
</div>

The global var's name is task. But your local var is also called task.
{% for task in project.tasks.all %}
{% include 'ProjectManager/views/task_view.html' with task=task%}
{%endfor%}
so i guess what you where trying to do is:
{% for task_local in project.tasks.all %}
{% include 'ProjectManager/views/task_view.html' with task_global_of_next_inheritance=task_local%}
{%endfor%}
but what happened is
{% for task_local in project.tasks.all %}
{% include 'ProjectManager/views/task_view.html' with task_global_of_next_inheritance=task_global%}
{%endfor%}
(using the global instead of the local var)
so you are just making the same call over and over again. if i am right, fix with
{% for task_local in project.tasks.all %}
{% include 'ProjectManager/views/task_view.html' with task=task_local%}
{%endfor%}

Related

Django Template: Exclude request.user from displaying user list

I have a simple problem. Below html code return list of all users whose liked blog. How can i exclude request user from list of them ?
<div class="collapse" id="likes">
<ul>
{% for like in instance.likes.all %}
<li>
{{like}}
</li>
{% endfor %}
</ul>
</div>
I tried as : {{like |request.user}} or something like this ,but no result. Thanks in advance
The easiest way to do this is probably using an {% if ... %} to filter out that particular user:
<div class="collapse" id="likes">
<ul>
{% for like in instance.likes.all %}
{% if like != request.user %}
<li>
{{like}}
</li>
{% endif %}
{% endfor %}
</ul>
</div>

Is it possible to custom django-tables2 template for a specific page in this case?

I'm using django-tables2 to render my data in tables in the template..
everything is rendered fine with pagination..
The Designer of our company wants to change the Display of data into blocks instead of simple table. the following picture may explain more.
I Want to ask if I can use Django tables2 in this case ..since I don't want to loose the pagination
Is it possible to custom the django_tables2/table.html file to only fit this case (because I'm using django-tables2 in many other pages in the project)?
Any other ideas may be helpful.
Thanks in advance :)
Yes, you can create a custom template (based on django_tables2/table.html) and set a specific table's template Meta attribute to its path:
import django_tables2 as tables
class Table(tables.Table):
# columns
class Meta:
template = 'table-blocks.html'
or use the template argument to the Table constructor:
table = Table(queryset, template='table-blocks.html')
or use the second argument of the {% render_table %} templatetag:
{% load django_tables2 %}
{% render_table queryset 'table-blocks.html' %}
I was having the same requirement and i had been able to do it. To achieve the desired results i have used bootstrap4 and modified the "django_tables2/bootstrap4.html" template. My modified template only displays blocks which can further be enhanced by embedding more css in it.
{% load django_tables2 %}
{% load i18n %}
{% block table-wrapper %}
<div class="container-fluid relative animatedParent animateOnce p-0" >
{% block table %}
{% block table.tbody %}
<div class="row no-gutters">
<div class="col-md-12">
<div class="pl-3 pr-3 my-3">
<div class="row">
{% for row in table.paginated_rows %}
{% block table.tbody.row %}
<div class="col-md-6 col-lg-3 my-3">
<div class="card r-0 no-b shadow2">
{% for column, cell in row.items %}
<div class="d-flex align-items-center justify-content-between">
<div class="card-body text-center p-5">
{% if column.localize == None %}{{ cell }}{% else %}{% if column.localize %}{{ cell|localize }}{% else %}{{ cell|unlocalize }}{% endif %}{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock table.tbody.row %}
{% empty %}
{% if table.empty_text %}
{% block table.tbody.empty_text %}
<tr><td colspan="{{ table.columns|length }}">{{ table.empty_text }}</td></tr>
{% endblock table.tbody.empty_text %}
{% endif %}
{% endfor %}
</div></div></div> </div>
{% endblock table.tbody %}
{% block table.tfoot %}
{% if table.has_footer %}
<tfoot {{ table.attrs.tfoot.as_html }}>
<tr>
{% for column in table.columns %}
<td {{ column.attrs.tf.as_html }}>{{ column.footer }}</td>
{% endfor %}
</tr>
</tfoot>
{% endif %}
{% endblock table.tfoot %}
{% endblock table %}
</div>
{% block pagination %}
{% if table.page and table.paginator.num_pages > 1 %}
<nav aria-label="Table navigation">
<ul class="pagination justify-content-center">
{% if table.page.has_previous %}
{% block pagination.previous %}
<li class="previous page-item">
<a href="{% querystring table.prefixed_page_field=table.page.previous_page_number %}" class="page-link">
<span aria-hidden="true">«</span>
{% trans 'previous' %}
</a>
</li>
{% endblock pagination.previous %}
{% endif %}
{% if table.page.has_previous or table.page.has_next %}
{% block pagination.range %}
{% for p in table.page|table_page_range:table.paginator %}
<li class="page-item{% if table.page.number == p %} active{% endif %}">
<a class="page-link" {% if p != '...' %}href="{% querystring table.prefixed_page_field=p %}"{% endif %}>
{{ p }}
</a>
</li>
{% endfor %}
{% endblock pagination.range %}
{% endif %}
{% if table.page.has_next %}
{% block pagination.next %}
<li class="next page-item">
<a href="{% querystring table.prefixed_page_field=table.page.next_page_number %}" class="page-link">
{% trans 'next' %}
<span aria-hidden="true">»</span>
</a>
</li>
{% endblock pagination.next %}
{% endif %}
</ul>
</nav>
{% endif %}
{% endblock pagination %}
{% endblock table-wrapper %}

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>

Django {% if forloop.first %} question

I have the following code in my template:
{% for object in object_list %}
{% with game=object.game %}
{% for category in object.game.objectmeta.categories.all %}
{% if category.name|title == 'Puzzle' %}
{% if forloop.first %}
<div class='side_header' id='dark_gamelink_side'>
<a class='actionheader' href=""></a>
</div>
{% endif %}
<div class='game_link' id='dark_gamelink'>
<a class='img_link' href="{% url game_view game.id game.title|slugify %}">
<img class='game_img' src='{{game|thumb:"78x65"}}' alt='{{game.title}}' />
</a>
<div class='top_game_title' style='padding:0'>
<a style='position:relative; top:-3px' id='yellowlink' href="{% url game_view game.id game.title|slugify %}">{{game.title}} -- {{category.name|title}}</a>
<img style='position:relative; top:1px; margin-left:12px' src='thumbsup.gif' width='17' height='18'/>
<span style='position:relative; top:-3px; font-size:10px; color:white'>99%</span>
</div>
{% if game.description|length > 65 %}
{{ game.description|slice:"65" }}...
{% else %}
{{ game.description }}
{% endif %}
</div>
{% if forloop.counter0 == 3 %}
<div class='more_games'><br/></div><div class='side_header' id='dark_gamelink_side'><a class='adventureheader' href=adventure.htm></a></div>
{% endif %}
{% endif %}
{%endfor%}
{% endwith %}
{% endfor %}
Now I'm using this:
{% if forloop.first %}
<div class='side_header' id='dark_gamelink_side'>
<a class='actionheader' href=""></a>
</div>
{% endif %}
to try to detect if this is the first iteration of the for loop immediately preceding it not the parent forloop. In other words I'm trying to detect if it's the 1st iteration of this for loop:
{% for category in object.game.objectmeta.categories.all %}
not this one:
{% for object in object_list %}
The way it is now isn't working because it's displaying this:
<div class='side_header' id='dark_gamelink_side'>
<a class='actionheader' href=""></a>
</div>
Twice. How to detect the first iteration of the nested forloop?
Edited:
I have never used these variables but I think forloop.parentloop.first should do it. If not blame me to have misunderstand the Django docs. ;-)
You should check if you are within the parentloop and and then within the first nested node. Please try this modified template. It should you give the right direction.
{% if forloop.parentloop.first %}
I am in the first loop of the parent
{% else %}
{% if forloop.first %}
<div class='side_header' id='dark_gamelink_side'>
<a class='actionheader' href=""></a>
</div>
{% endif %}
{% endif %}
I think the best way to solve this isn't to detect if this is the first iteration in the loop, but rather to write your HTML so that is outside the loop entirely.
You should only be writing HTML elements in the for loop that you actually want repeated for each iteration. If that doesn't work, rethink how you're providing the data to your view (object_list, game, category, etc) so that you can write your markup more easily.
The beginning of your view will probably look something like this:
<div class='side_header' id='dark_gamelink_side'>
<a class='actionheader' href=""></a>
</div>
{% for object in object_list %}
{% with game=object.game %}
{% for category in object.game.objectmeta.categories.all %}
{% if category.name|title == 'Puzzle' %}

Pagination problem with Django haystack

i'm using django-haystack with simple engine, the search is fine, but the pagination is not working. This is the code of my search results template
{% if query %}
<br>
<div id="contenido_pagina">
{% for result in page.object_list %}
{% if result.object.get_model == '[Video] ' %}
{% if result.object.publicar %}
<div class="salida_search">
{{result.object.get_model}}{{result.object.nombre}}<br>
<div class="resumen_search">
{{result.object.sinopsis|safe|truncatewords:"30"}}
</div>
<div class="link_search">
{{result.object.anio}}
</div>
</div>
{% endif %}
{% else %}
<div class="salida_search">
{{result.object.get_model}}{{result.object.titulo}}<br>
<div class="resumen_search">
{% if result.object.contenido %}
{{result.object.contenido|safe|truncatewords:"30"}}
{% else %}
{{result.object.sinopsis|safe|truncatewords:"30"}}
{% endif %}
</div>
<div class="link_search">
{{result.object.fecha|date:"d M Y"}}
</div>
</div>
{% endif %}
{% empty %}
<div>La busqueda <span class="highlighted">{{query}}</span> no obtuvo ningun resultado</div>
{% endfor %}
{% if page.has_previous or page.has_next %}
<div>
{% if page.has_previous %}{% endif %}« Anterior{% if page.has_previous %}{% endif %}
|
{% if page.has_next %}{% endif %}Siguiente »{% if page.has_next %}{% endif %}
</div>
{% endif %}
</div>
<br>
{% else %}
{# Show some example queries to run, maybe query syntax, something else? #}
{% endif %}
when i go to the next page i see the same objects that first page. What i am doing wrong??
I had this issue as well. From debugging the code it looks like it's an issue with the paginator and the searchqueryset. Unfortunately i didn't have more time to devote to it and ended up moving on to whoosh for development environment.
Just encountered this. Seems as though it's a known limitation of the simple backend.
https://github.com/toastdriven/django-haystack/issues/320

Categories