Django templates - comparing variables to integer constants - django

Seems like elementary question, and yet can't get it work
{% if iterator.next > 10 %}
Do smth
{% endif %}
Two issues. First, this code just won't work (the code in the if-condition never implemented even when the condition seems to hold true), and second issue - the ">" sign is highlighted as if it where the closing tag of the closest open tag. Any ideas how to fix the first issue and is it all right with second issues ? Maybe there's some elegant syntax that I am missing and that would remove this ambiguity for the text editor ?

iterator.next may be a string which would result in the statement being False.
Try creating a custom filter to convert it to an int. For example create "my_filters.py":
# templatetags/my_filters.py
from django import template
register = template.Library()
#register.filter()
def to_int(value):
return int(value)
Then in your template:
{% load my_filters %}
{% if iterator.next|to_int > 10 %}
Do smth
{% endif %}
More on custom tags and filters here
I wouldn't worry about the highlighting, this may just be your IDE. I recommend using PyCharm for Django development

Django's docs says that you can use > with if tag:
{% if somevar < 100 %}
This appears if variable somevar is less than 100.
{% endif %}
take a look at documentation: https://docs.djangoproject.com/en/1.9/ref/templates/builtins/
maybe you are missing something else?

Related

VSCode breaks Django template tags with newline

Problem:
{% extends 'base.html' %} {% block title %} Dashboard {% endblock %} {% block pagetitle %}
becomes
{% extends 'base.html' %} {% block title %} Dashboard {% endblock %} {% block
pagetitle %}
Note that the {% tag %} is being broken with a new line. This causes syntax errors with django templates.
I've tried most top django template extensions and this does not fix the issue.
I've also tried these settings:
"[html]": {
"editor.formatOnSave": false,
},
"html.format.wrapLineLength": 0,
"html.format.enable": false,
"prettier.disableLanguages": ["html"]
Desired Behavior:
Automatically format *.html files, while preserving django template tags, not breaking them up with newlines.
Sub-optimal (but acceptable) behavior: don't format *.html files at all.
I had the same issue and the only way I found that solved it is to disable the default HTML formatter. Unfortunately, I did not find a way to make it format Django template tags correctly. You can do the same if you go to VS Code Preferences > Settings > User > Extensions > HTML and uncheck 'Enable/disable default HTML formatter'.
I solved this by following this advice: https://stackoverflow.com/a/73892745/1257347
TLDR: install the djLint extension (and remember to do $ pip install djlint)
I got it to work by simply adding {{""}} between the {% tag %} that were being broken.
Example:
{% extends 'main/base.html' %} {% block title_block %}Homepage{% endblock%}
{{""}} {%block style_ref_block%}{%endblock%} {{""}} {% block body_block %}
This Didn't work for me.
The hack I found was to set the vscode language to jinja instead of the auto detected html
reference
I've also just experienced vs-code misbehaving on django template tags (i.e. deleting curly braces).
I don't like the idea of disabling HTML formatting just to support templates (i.e. vs-code Preferences/Settings/Extensions/HTML: disable (uncheck) "HTML>Format:Enable"). This is arguably a step backwards, but it does stop vs-code misbehaving.
Instead, I chose to install (vs-code Preferences/Extensions) the 'Django' extension, by Baptiste Darthenay. This was a better way to go, because it works, gracefully, preserves native vs-code HTML formatting, and includes a nice set of django snippits, which saves me keystrokes when embedding template code. Tada!
BTW, before finding Baptiste's awesome extension, I also tried keeping vs-code HTML formatting enabled, AND enabling 'HTML>Format:Templating', which promised to "Honor django and other templating language tags"; it did not.

Django jinja if-elif statement breaks with ==

So on my front-end, I want to show some HTML only if the user belongs to one of 2 groups: 'admins' or 'clerks'. There are 3 groups of users: 'admins', 'clerks', and 'sellers'. Here is my front-end code:
{% if user.groups.all.0 == "admins" %}
<h1>Some HTML</h1>
{% elif user.groups.all.0 == "clerks" %}
<h1>Some HTML</h1>
{% endif %}
When I run this code, the HTML shows for the admins. But that of the clerks does not show. I have tried printing out the group to be sure that the spelling and the casing were the same, and they were the same. And Django does not throw an error. It only works if I rewrite the code as follows:
{% if user.groups.all.0 == "admins" %}
<h1>Some HTML</h1>
{% elif user.groups.all.0 != "sellers" %}
<h1>Some HTML</h1>
{% endif %}
But I feel like this is not good design. Please am I missing something? Thank you all in advance
First of all, is a not practical idea for too many reasons.
Think that using that method you are getting possibilities and processing that don't correspond to the templates. The templates engine philosophy is just basic and no important logic.
A way to have more control and more practical is using a flag. For example
groups_permited_for_this=["admins","clerks",...]
Permited =False
for group in user.Groups.all:
if group.name in groups_permited_for_this:
Permited =True
Pass it as context and then use a Jinja if statement.
So I resolved the issue in a slightly different way from the one above:
First, I created a folder called 'templatetags' inside the app.
Then I created 2 files in it:
An empty 'init.py' file
A 'cust_auth.py'(for custom authentication) file
Inside the 'cust_auth.py' file I wrote a function that does a similar thing as in #Paulo Aguilar's answer above:
from django import template
from django.contrib.auth.models import Group
register = template.Library()
#register.filter(name='has_group')
def has_group(user, group_name):
group = Group.objects.get(name=group_name)
return True if group in user.groups.all() else False
Then in my template, I loaded the 'cust_auth.py' file at the top:
{% load auth_extras %}
Then I did the logic I was looking for:
{% if user|has_group:"admins" %}
<h1>Some HTML</h1>
{% endif %}
I preferred this because I think over the cause of my application, I will want more custom authentications
Thank you Paulo and whoever posts

Django template custom tag as boolean

This seems such a simple thing but I can't seem to get it to work for one, and two I can't seem to be getting a straight forward answer online on wether it can or can't be done.
I just want a simple tag that will work like so
{% if my_tag %}
render something
{% else %}
render something else
{% endif %}
now I don't care about filters or any other ways you might be able to do the same thing, I want it to look exactly like that, and work like described, I have a simple tag made that actually does return True or False as needed, and it's called if I call the tag like this
{% my_tag %}
however it does't get called if I add an if in front of the tag, is a feature this simple and logical not implemented?
Like the link to the potential duplicate states, you can use an assignment tag similar to the following that will return the current time:
#register.assignment_tag
def get_current_time(format_string):
return datetime.datetime.now().strftime(format_string)
Within your template you can then do what you are desiring to do:
{% if get_current_time %}
...show time
{% else %}
...don't show time
{% endif %}

Django Pass Multiple Parameters to Custom Template Filter Inside If Statement

I have an issue. I've written a custom template tag with a function signature like this-
def has_paid_for_article(article, request):
Now, in my template tag I have a conditional statement to determine whether a user can download an article or not (this is determined by if the article is older than two years or the logged in user has paid for the article). Here's the snippet-
{% if article|is_older_than_two_years %}
<span class="amp">& </span>{% get_article_download_link article %}
{% else %}
download
{% endif %}
The aforementioned snippet works fine, however I need to call the has_paid_for_article() function inside of a conditional statement. I've tried the following ways to make this happen-
{% if article|is_older_than_two_years or article|request|has_paid_for_article %}
,
{% if article|is_older_than_two_years or [article, request]|has_paid_for_article %}
This one works outside of the conditional statement-
{% if article|is_older_than_two_years or has_paid_for_article article request %}
What would be the correct syntax here? Also, I've read other posts on the topic, I CANNOT put this logic in the view. I won't go into detail, but with the way it works, that is not an option. Thank you!
Try
{% if article|is_older_than_two_years or article|has_paid_for_article:request %}
See Writing custom template filters

Django: How do I get the number of elements returned in a database call?

This seems to me like a very simple question, but I can't seem to find the answer.
All I need to do is determine the number of objects returned by a database query.
The specific circumstance is this: I have a model named Student. This model has a ManyToManyField member named courses_current, which relates to a table of Course models. When I pass my Student instance to a template, I want to be able to do something like the following (the syntax may not be exact, but you'll get the basic idea):
<div id="classes">
{% if student.classes_current.all.size == 0 %}
<h1> HEY! YOU AREN'T TAKING ANY CLASSES! REGISTER NOW!
{% else %}
Here are your courses:
<!-- ... -->
{% endif %}
</div>
Now, I'm fairly certain that X_set.all.size is not a real thing. In the manage.py shell I can just use len(student.classes_current.all()), but I don't know of any way to use built-in functions, and "dictionary-like objects" don't have .size() functions, so I'm at a loss. I'm sure there's a very simple solution (or at least I hope there is), but I can't seem to find it.
{{ student.classes_current.all.count }} but be warned that it doesn't fetch the objects so you will need to do a separate query if you want to loop over them.
If you need loop over the classes for tag has way to get what you need.
{% for cl in student.current_classes.all %}
{{ cl }}
{% empty %}
<h1>Hey! ...</h1>
{% endfor %}
Documentation https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#for-empty