How to call a function inside a django html template - python

I'm new to Django. The question is rather basic and I read some google links and documents, apparently I can't resolve it.
Basically:
I need to access the blog entries of a particular blog inside html file, but apparently blog.blogentry_set() is not working as expected. Could someone help please. Here is the code I tried:
models.py file:
class Blog(models.Model):
subject = models.CharField(max_length = 20)
...
class BlogEntry(models.Model):
ref = models.ForeignKey(Blog)
...
index.html file:
{% for blog in blogs %}
<p>{{ blog.subject}}</p>
<div>
<p>{{blog.date}}</p>
{% for entry in blog.blogentry_set.all() %}
{{entry.text}}
{% endfor %}
</div>
{% endfor %}
I tried to delete (), and this helps to take off the error message, but the entry text is not printed as expected, so something is again not working.
I heard in template language, to call function we do not need (), but then how do we pass arguments?
also, I am asking to myself: do I need to 'load' some file here? Please help :D

You can't pass an argument to a callable attribute like this. Either pull the value in the view, or write a custom template tag to do it.

To address the first problem ("blog.blogentry_set() is not working as expected"), remove the parenthesis after the .all like:
{% for entry in blog.blogentry_set.all %}
{{entry.text}}
{% endfor %}
The second issue ("to call function we do not need (), but then how do we pass arguments?"), is amply addressed by #Varnan K's answer. You will likely have to create a custom template tag.

Related

Could not parse the remainder: '(audio_only=True)'

in my templates/videos.html,
<div class="grid grid-cols-3 gap-2">
{% for vid in videos.streams.filter(audio_only=True) %}
{{vid.resolution}}
{% endfor %}
</div>
Error is,
Could not parse the remainder: '(audio_only=True)' from 'videos.streams.filter(audio_only=True)'
I can solve this when i pass all_videos = videos.streams.filter(audio_only=True) from my views.py as context, and in templates/videos.html i replace videos.streams.filter(audio_only=True) with all_videos,
but I want to know that is there any other method to solve this
but I want to know that is there any other method to solve this.
You could add an extra property/method with no parameters to the Video model and call that property to obtain the filtered queryset.
For example:
class Video(models.Model):
# …
#property
def audio_streams(self):
return self.streams.filter(audio_only=True)
and then thus use {% for video in videos.audio_streams %}. But regardless, the Django template language has been deliberately restricted to prevent people from writing this: a template should implement rendering logic, not business logic: business logic belongs in the models and the views. So the only clean solution is to filter in the view, not the template.

Link to a page in django cms, first check if it exists

I often do things like this in a django template, with django-cms:
{% load cms_tags %}
Imprint
On production, this fails silently, and the href attribute is empty. On development, I'm forced to insert the page with id "imprint", otherwise I get a "DoesNotExist" exception.
How can I improve this situation? Maybe I'm looking for something like
{% if 'imprint'|cms_page_exists %}
...the link and stuff...
Is there a known best practice for this (not quite seldom) use case? Or do you all use it as shown first?
You could assign a tag result to a variable and then check is it empty:
{% page_url 'imprint' as url %}
{% if url %}
Imprint
{% endif %}
Other ways imply creating your own template tag or filters, so the above is the simplest one IMHO.
See also an example in the docs.

Explain the code snippet in Django

I am pretty new to Django. I am fiddling with zinnia to customize it and setting it up with my own theme/template etc. The main content displayed in the default template is following:
{% for object in object_list %}
{% include object.content_template with object_content=object.html_preview continue_reading=1 %}
{% empty %}
I understand that include includes the template inside a page. But what I cannot comprehend is: how do I find the relevant template being rendered? What is content_template? Please help me in understanding this snippet.
The template name (content_template) is being fetched from the database. It is a property of the model ContentTemplateEntry and defaults to zinnia/_entry_detail.html.

Django template check for empty when I have an if inside a for

I have the following code in my template:
{% for req in user.requests_made_set.all %}
{% if not req.is_published %}
{{ req }}
{% endif %}
{% empty %}
No requests
{% endfor %}
If there are some requests but none has the is_published = True then how could I output a message (like "No requests") ?? I'd only like to use Django templates and not do it in my view!
Thanks
Even if this might be possible to achieve in the template, I (and probably many other people) would advise against it. To achieve this, you basically need to find out whether there are any objects in the database matching some criteria. That is certainly not something that belongs into a template.
Templates are intended to be used to define how stuff is displayed. The task you're solving is determining what stuff to display. This definitely belongs in a view and not a template.
If you want to avoid placing it in a view just because you want the information to appear on each page, regardless of the view, consider using a context processor which would add the required information to your template context automatically, or writing a template tag that would solve this for you.

Any way to make {% extends '...' %} conditional? - Django

I would like to share a template between AJAX and regualr HTTP calls, the only difference is that one template needs to be served with the base.html html, the other one without.
Any idea?
The other answers require you to pass an additional context variable. But as long as you can access the request object, there is no need:
{% extends request.is_ajax|yesno:"app/base_ajax.html,app/base.html" %}
I found this to be much more convenient.
Use a variable.
{% extends base_template %}
and in your view, set it to "base.html" in your view, or a new "ajax.html" file which just provides the block and nothing else.
{% extends override_base|default:'base.html' %}
P.s. I know this is an old question, but I found it when searching for an answer. Maybe it'll help someone else with the same problem.
You can use {% extends variable %}
Pass a variable base template name in when you create the context in the view.
http://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#extends

Categories

Resources