Iterate through Django queryset within template - django

I have created a custom filter that returns a queryset of objects.
in: templatetags
#register.filter(name = 'create_html_for_deleting_notes')
def create_html_for_deleting_notes(task_pk):
corresponding_notes = Note.objects.filter(its_task = Task.objects.filter(pk = task_pk))
return(corresponding_notes)
in template:
{% for corresponding_task in corresponding_tasks %}
<h5>{{ corresponding_task | create_html_for_deleting_notes }}<h5/>
{% endfor %}
This works in printing out my queryset. I would like to iterate through that queryset, something like:
in template:
{% for corresponding_task in corresponding_tasks %}
{% for note in corresponding_task | create_html_for_deleting_notes %}
{{ note }}
{% endfor %}
{% endfor %}
But this gives me the error 'for statements should use the format "for x in y"'
Thank you for the help!

You need to remove the spaces around the filter | character.
However, I don't think you need the filter at all. You didn't post your model, but it seems like you have a foreignkey relationship between Task and Note, so you should just use the reverse accessor:
{% for corresponding_task in corresponding_tasks %}
{% for note in corresponding_task.note_set.all %}
{{ note }}
{% endfor %}
{% endfor %}

Related

How to use {{ variable }} in {% if is_exist %} in Django template?

Like I asked in the title, I wanna do something like the below in Django.
{% for i in "xxxxx" %}
{% if store{{ forloop.counter }} %}
...
{% endif %}
{% endfor %}
I pass variables named 'store1', 'store2', and 'store3' from views.py
However, an error happens saying
"Could not parse the remainder: '{{' from 'store{{'"
, which seems like {{ }} can't be used inside {% %}
Does anyone know how to do this?
You can't do this in the Django template language.
A better approach would be to pass the stores to the template as a list,
def my_view(request):
stores = ['store1', 'store2', ...]
return render(request, 'mytemplate.html', {'stores': stores}
then loop through the list in the template:
{% for store in stores %}
{{ store }}
{% endfor %}

set_all to get value from custom model manager in django

I have two models:
Tutorial
--> consist of published manager which returns queryset when is_published=True
Category
In template, I am passing Category object.
{% for category in categories %}
{% for tutorial in category.tutorial_set.all %}
{{ tutorial.title }}
{% endfor %}
{% endfor %}
Instead of getting all, I want to get from published manager like: Tutorials.published.all()
How to achieve this?
Well I guess you can do something like
class TutuorialManager(models.Manager):
def published(self):
return self.filter(is_published = True)
then in the views you can do something like..
{% for category in categories %}
{% for tutorial in category.tutorial_set.published.all %}
{{ tutorial.title }}
{% endfor %}
{% endfor %}

Django template: check for empty query set

Is there a way to check for an empty query set in the Django template? In the example below, I only want the NOTES header to be displayed if there are notes.
If I put an {% empty %} inside the "for" then it does display whatever is inside the empty tag, so it knows it's empty.
I'm hoping for something that does not involve running the query twice.
{% if notes - want something here that works %}
NOTES:
{% for note in notes %}
{{note.text}}
{% endfor %}
{% endif %}
Clarification: the above example "if notes" does not work - it still displays the header even with an empty query set.
Here's a simplified version of the view
sql = "select * from app_notes, app_trips where"
notes = trip_notes.objects.raw(sql,(user_id,))
return render_to_response(template, {"notes":notes},context_instance=RequestContext(request))
Edit: the view select selects from multiple tables.
Have a look at the {% empty %} tag.
Example from the documentation
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athletes in this list.</li>
{% endfor %}
</ul>
Link: https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#for-empty
If you are interested in a table, or some kind of heading if there are results, add the forloop.first:
{% for athlete in athlete_list %}
{% if forloop.first %}
Athlete Name:
{% endif %}
{{ athlete.name }}
{% empty %}
Sorry, no athletes in this list.
{% endfor %}
Try {% if notes.all %}. It works for me.
In your view check whether notes is empty or not. If it is then you pass None instead:
{"notes": None}
In your template you use {% if notes %} as normal.
It's unfortunate that you're stuck using a raw query set - they're missing a lot of useful behavior.
You could convert the raw query set into a list in the view:
notes_as_list = list(notes)
return render_to_response(template, {"notes":notes_as_list},context_instance=RequestContext(request))
Then check it as a boolean in the template:
{% if notes %}
Header
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
You could also make it happen without conversions using forloop.first:
{% for note in notes %}
{% if forloop.first %}
Header
{% endif %}
{{ note.text }}
{% endfor %}
What about:
{% if notes != None %}
{% if notes %}
NOTES:
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
{% else %}
NO NOTES AT ALL
{% endif %}
Your original solution
{% if notes %}
Header
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
Works now with Django 1.7 and thanks to QuerySet caching, it does not cost and extra query.
Often the right way to do this is to use the {% with ... %} tag. This caches the query so it runs only once and also gives you more flexibility with your markup than using {% empty %}.
{% with notes as my_notes %}
{% if my_notes %}
<ul>
{% for note in my_notes %}
<li>{{ note }}</li>
{% endfor %}
</ul>
{% else %}
<p>Sorry, no notes available</p>
{% endif %}
{% endwith %}
With this particular example I'm not sure how useful it is but if you're querying Many-to-Many field, for instance, it's likely what you want to do.
Use {% empty %} in django templates
{% if list_data %}
{% for data in list_data %}
{{ data.field_1 }}
{% endfor %}
{% else %}
<p>No data found!</p>
{% endif %}
We can write above code with {% empty %}.
{% for data in list_data %}
{{ data.field_1 }}
{% empty %}
<p>No data found!</p>
{% endfor %}

Dictionary with arrays in django templates

I have dictionary with arrays inside:
dicarr = {'category': ['post1','post2', 'e.g.'], 'category2': ['post1','post2']}
Array is filled in one cycle:
dicarr = {}
for category in Categories.objects.all():
category_posts = Post.objects.filter(category=category)
dicarr[category] = [post for post in category_posts ]
How can i get access to array from django template? I tried:
{% for arrdic in dicarr %}
{{ arrdic.name }}
{% for i in arrdic.posts %}
{{ i.name }}
{% endfor %}
{% endfor %}
But isn't working.
Assuming you have a foreign key pointing to Category on your Post, you don't even need to do it this complicated. All you need to is pass this to the template:
categories = Category.objects.all()
Then you can iterate like this in the template:
{% for category in categories %}
{{ category.name }}
{% for post in categories.post_set.all %}
{{ post.name }}
{% endfor %}
{% endfor %}
You can do this with any foreign key relationships. Hope that answers your question!
Following your original code, your template should be (also see for tag docs):
{% for category, posts in dicarr.items %}
{{ category.name }}
{% for post in posts %}
{{ post.name }}
{% endfor %}
{% endfor %}
But this isn't the best way to do this, because your view will produce number of queries equal to the number of categories. See my answer to a similar question for a more efficient solutions.

Is there any way to reuse template tag value in Django templates?

For example, let's say there is a custom template tag
{% custom_tag "parameter" %}
This tag requires some serious database work to calculate.
Now I need to have something like that (pseudocode):
if {% custom_tag "parameter" %}
....
else
....
I know that with context variables I can do just:
{% with variable.x.y.z as v %}
{% if v %}
Blah-Blah-Blah {{ v }}
{% else %}
No value
{% endif %}
{% endwith %}
But is there any way do achieve this with template tag value?
EDIT:
The only option I've came up with so far is to make a filter out of my template tag:
{% if "parameter" | custom_tag %}
Blah {{ "parameter" | custom_tag }}
{% else %}
....
{% endif %}
But this option makes custom_tag execute twice, and that's not good performance-wise
i haven't test it but i guess that you can add a variable to the context from your custom tag.. maybe this will help you
http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#setting-a-variable-in-the-context
I believe you can assign the results of filtering to a variable and use it. This way the filter will only get called once. From the docs: with: Caches a complex variable under a simpler name. This is useful when accessing an "expensive" method (e.g., one that hits the database) multiple times.
{% with "parameter" | custom_tag as result %}
{% if result %}
Blah {{ result }}
{% else %}
....
{% endif %}
{% endwith %}