The If equal not working in Django Template - python

I am able to fetch these two values in the Django HTML template :
{{ user.get_username }}
{{ post.user }}
But when I use them further to compare their values in an IF condition, it doesn't work.
{%for post in post%}
<h1>{{post.title}}</h1>
<h2>{{post.content}}</h2>
<p>{{post.date}}</p>
{%if user.is_authenticated%}
<h3> {{ user.get_username }}</h3>
<h3> {{post.user}} </h3>
{%ifequal user.get_username post.user%}
<form action="{%url 'post_delete' post.id %}" method="POST">
{%csrf_token%}
<button type="submit">Delete</button>
</form>
{%endifequal%}
{%endif%}
{%endfor%}
I've also tried {% if user.get_username == post.user %} as well, but it didn't help either.
Please help. I need the delete button only against the posts of logged in user.

{{ user.get_username }} and {{ post.user }} are different objects.
If you want to compare the "string" representation of both (thats what you see in the rendered template), you have to convert {{ post.user }} to a string. (I'd convert them both, since I don't know if you user_name is also a string (it should be, though).
Use:
{% if user.get_username|stringformat:'s' == post.user|stringformat:'s' %}
Check documentation here:
Django Template Tag: Stringformat
Python Conversion Types (I.e. 's')

Did you tried solution provided here:
compare two variables in jinja2 template
{% if user.get_username|string() == post.user|string() %}

{% if user == post.user %} worked for me.
Looks like 'user.get_username' was not working. Just 'user' worked. I wonder why though.

{% if notification.status|stringformat:'s' == 'Approved' %}
<td><div class="badge badge-success">{{ notification.status }}</div></td>
{% else %}
<td>{{ notification.status }}</td>
`{% endif %}'

Related

How to add an attribute to the form tag itself and not just a field in Django?

I am having trouble stopping bots filling in spam while letting through legit users. I have a honeypot field with autocomplete="off" attribute but it doesn't seem to be working. From what i've read, the best cross browser solution is to add autocomplete="false" to the main form tag itself, e.g. <form autocomplete="false">...</form>. What is the best way to do this in Django?
Just do that in your template where the form is added.
In a template you'd typically do something like;
<form autocomplete="false">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.label }}
{{ field }}
{{ field.help_text }}
{% endfor %}
So just add whatever you want to the form tag.
You should probably also have a look at including recaptcha if you've got spam problems.
And remember that v3 doesn't require any selecting street lights etc
https://pypi.org/project/django-recaptcha/

How can I show a specific django field in html?

So I want to do what the title says and I don't know how since I'm new at this.
<p>{{ form.description }}</p>
That's the way I show information from different models in a listing using
{% for form in forms %}
But I want to show the description of an specific object.
Thanks in advance.
<form method="post" novalidate>{% csrf_token %}
{{ form.non_field_errors }}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field.errors }}
{{ hidden_field }}
{% endfor %}
<table border="1">
{% for field in form.visible_fields %}
<tr>
<th>{{ field.label_tag }}</th>
<td>
{{ field.errors }}
{{ field }}
{{ field.help_text }}
</td>
</tr>
{% endfor %}
Look this article: [link][1]https://simpleisbetterthancomplex.com/article/2017/08/19/how-to-render-django-form-manually.html
Usually django templates will be filled with the data rendered from the django views as dictionary and these will be callable in templates using django template tags "{{tag_name}}"
Here you will be rendering all the forms as a list inside the dictionary so you can show each form by looping it.
{% for form in forms %}
{{form.description}}
{% endfor %}
Like this, you can show each form's data. Instead of this if you only want to show a specific form's data then the proper way is to render the view with the specific form's data and show data in template using the template tag {{form.description}}
Check the django documentation : https://docs.djangoproject.com/en/2.1/topics/templates/

Naming collision in Django Template

I'm having a peculiar problem with a django template I'm setting up: I have a {{ name }} variable that I'm passing to my template, and at the same time, I have a notes list coming from a client-side api that has both a {{ name }} and a {{ body }}.
Whenever I try to print out the name of the note, the other {{ name }} shows up. Which is odd. Here's my code for the notes:
<div class="notes">
{% for note in notes %}
<p><strong>{{ name }}</strong></p>
<p>{{ body }}</p>
{% endfor %}
</div>
Am I doing something wrong? Is there a context operator I can use or something?
<div class="notes">
{% for note in notes %}
<p><strong>{{ note.name }}</strong></p>
<p>{{ note.body }}</p>
{% endfor %}
</div>
This is a common mistake that is made when working with Handlebars alongside Django since Handlebars changes scope automatically for you. All you need to do is refer to the note variable you created with the for loop:
<div class="notes">
{% for note in notes %}
<p><strong>{{ note.name }}</strong></p>
<p>{{ note.body }}</p>
{% endfor %}
</div>
More info here: https://docs.djangoproject.com/en/1.5/ref/templates/builtins/#std:templatetag-for

Determine empty template variable in Django

I'm not able to determine whether a variable is empty when used in the template.
I've iterated through the whole collection and in each I'm looking for a variable narrative_text.
I tested the empty variable by
{% ifnotequal narratives.narrative_text '' %}
I notice the control enters this block, but prints nothing/blank when the
{{ narratives.narrative_text }}
is encountered.
So, how do I precisely check if the variable is empty?
I read the docs and found out that invalid/empty template variables are replaced by ''.
The doc says that
the template system inserts the value of the TEMPLATE_STRING_IF_INVALID setting.
Do we have to explicitly enter that into the settings.py? I tried doing so but still I haven't been able to make it work.
c=Context({
"narratives_list":all_narratives,
"patient_name":care_seeker_name
})
all_narratives is returned by a pymongo database call.
{% for narratives in narratives_list %}
<tr>
<td class = "date_col">
7 Aug, 2012
</td>
{% ifnotequal narratives.narrative_text '' %}
<td>
<div class = "narrative">
( text narrative )
<b>
{{ narratives.about }}
</b>
<br><br>
{{ narratives.narrative_text }}
</div>
</td>
{% else %}
<td>
<div class="scans">
<div class="gallery">
<b> {{ narratives.about }}</b>
<br><br>
<a href="https://udhc1-nodejstest.rhcloud.com/my_image/{{ narratives.file_id }}">
<img src="https://udhc1-nodejstest.rhcloud.com/my_image/{{ narratives.file_id }}" width="72" height="72" alt="" />
</a>
</div>
</div>
</td>
{% endifnotequal %}
Pipe through length and do your test against that value.
{% if narratives.narrative_text|length > 0 %}
{{ narratives.narrative_text }}
{% else %}
None
{% endif %}
Just use {% if narratives.narrative_text %}, I think. It will use Python's implicit false, which applies for empty strings, empty arrays, empty dicts, None, False, 0 etc..
Just confirmed via my own code using django 2.1.3 and python 3.5 and 3.7 that the following works:
{% if narratives.narrative_text %}
# do something
{{ narratives.narrative_text }}
{% else %}
# do something else
None # displays "None"
{% endif %}
I think that the best and obvious solution would be, in Django Template language:
{% if objects is not None %}
{% for obj in objects %}
{{obj}} // Do your stuff here
{% empty %}
No results. // No results case
{% endfor %}
{% endif %}
In case the variable objects is not set, nothing will be printed out.
I had similar difficulties.
Hope it helps.
You can write Custom template filter, is_empty to check. Return false if variable is empty and true if value exists.
{% if narratives.narrative_text|is_empty %}
# dosomthing
{% else %}
# dosomthing
{% endif %}
I've used jijnja which is a lot similar and simpler and I think it would work if you do
{% if not narratives.narrative_text %}
// do something
{% else %}
// do something else with or without {{ narratives.narrative_text }}
{% endif %}
It uses python implicit True/False,None, etc to do the job.
In simplest terms use python variables inside {{ }} and conditionals,etc inside {% %}

Is there a way to hide the csrf label while looping through form using Flask and Flask-WTForms?

I have very simple contact form and I would like to hide the label somehow so that it doesn't show Csrf Token. I am using Flask and Flask-WTForms and am rendering the form like this:
{% for field in form %}
{{ field.label }}
{{ field }}
{% endfor %}
So basically this shows my inputs correctly and the csrf oen is hidden but the label isn't hidden? Should I get over it and implicitly say form.field_name instead of looping through the form or is there a way to handle this "corner case".
I was thinking about doing a logical check in either the for loop declaration or the label declaration but so far I haven't found anything in the documentation that has worked.
Thanks
EDIT: I have "fixed" the problem by doing this but it feels kinda dirty and hacky which I don't like I am still open to a better solution:
{% if not loop.first %}
{{ field.label }}
{% endif %}
If you want a more general solution that works for all hidden fields instead of just the CSRF token:
{{ form.hidden_tag() }}
{% for field in form if field.widget.input_type != 'hidden' %}
{{ field.label }}
{{ field }}
{% endfor %}
form.hidden_tag() is supplied by Flask-WTF.
Just to add to JD's excellent answer...
For those stumbling across this question: You can avoid losing the (csrf) hidden field (and thus protection) by adding the condition "if field.widget.input_type!='hidden' " specifically to the label instead of to the form iterator.
i.e.:
not
{{ form.hidden_tag() }}
{% for field in form if field.widget.input_type != 'hidden' %}
{{ field.label }}
{{ field }}
{% endfor %}
but
{{ form.hidden_tag() }}
{% for field in form %}
{% if field.widget.input_type != 'hidden' %} {{ field.label }} {% endif %}
{{ field }}
{% endfor %}
I think this should work too:
{% for field in form if field.id != 'csrf_token' %}
{{ field.label }}
{{ field }}
{% endfor %}
I have found the way to do it like this:
{% if field.id != 'csrf_token' %}
I believe this to be less hacky. I found this from modifying the example here in the docs.
I made a macro recently to submit forms through ajax in order to not reload the webpage and send it to the api directly.
{% macro render_fields3(form, form_name, method) %}
<form class="ajax" name={{ form_name }} method={{ method }}>
{{ form.hidden_tag() }}
{% for field in form if field.widget.input_type != 'hidden' %}
<dt>{{ field.label }}
<dd>{{field(id=field.name + method)|safe}}
{% if field.errors %}
<ul class=errors>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</dd>
{% endfor %}
</form>
{% endmacro %}

Categories

Resources