Does django accept Jinja loop together with condintion in one line? - django

There's a wonderful example in Jinja docs regarding how not to use break:
{% for user in users if not user.hidden %}
<li>{{ user.username|e }}</li>
{% endfor %}
However when trying to use similar approach in Django template it gives me error:
TemplateSyntaxError at /childminder/task-list/
'for' statements should use the format 'for x in y': for link in form.links if link.status == form.status
Original code:
{% for link in form.links if link.status == form.status %}
{% url link.url id=application_id %}
{% else %}
{% for link in form.links if link.status == "Other" %}
{% url link.url id=application_id %}
{% endfor %}
{% endfor %}
Point is that I list of links in a list of forms (so those links belongs to specific form only), and there's status and url in that list of links. IF all link statuses didn't match form statuses THEN search for link status Other and print it's link.
Can't come up with another approach. Just adding one more link_default object to a form doesn't sound too good for me.

Related

How to show the first true element after if condition in for loop in django template?

I have a for loop in Django template. After that, I check for coincidences. But in some cases, there are might be 3 coincidences. I need to show only the first coincidence. Now, my code returns the name for 3 times, because, there are 3 coincidences
{% for ip in ips %}
{% if d.name == ip.name %}
<strong>{{ d.name}} </strong>
{% endif %}
{% endfor %}
SOLUTION
It is impossible to break forloop in django template, so I decided to change in views.py through queryset distinction of similar names
ips = Point.objects.defer('point').order_by('name').distinct('name')
I don't recommend doing this in Django Template , but in views itself. But if you can't then you can use {{ forloop|break }}.
Something like this :
{% for ip in ips %}
{% if d.name == ip.name %}
{{ forloop|break }}
<strong>{{ d.name}} </strong>
{% endif %}
{% endfor %}
Check the small snippet example here...

How can I use current object as variable

I'm a complete beginner at django and currently trying to create a library website. Users can issue books, and I want users who have done so, to see 2 extra buttons: unissue and extend. In my mind, this is what I want to be able to write:
{% for b in Borrower %}
{% if b.book == {{book}} %}
{% if b.student == {{user}}%}
#buttons
{% endif %}
{% endif %}
{% endfor %}
Obviously the error happens at {{book}} and {{user}} because it cannot parse the rest. I'm not sure what the correct syntax is to access current object and user being viewed.

Django check form error code in template

I am using Django 1.10 and trying to find a way to check the error code of a form inside of the template. So I tried a few things, like errors.as_data or errors.as_json, but I was unable to parse the different values (except by using javascript). Could it be something like this ?
<p>{% for key, value in form.errors.items %}
{{ value }}
{% if code == 'inactive_account'%}
// do some stuff
{% endif %}
{% endfor %}
</p>
But I don't know how to get this error code. Any suggestion ?
PS : I know that a solution would be to do it inside of the view, but since I am using a django already-made one, I would prefer not to do it.
The dictionary form.errors does not contain the ValidationError instances. You need to use the as_data method.
Note that you need to loop through the list of errors for each key, and then you can check the code.
{% for key, key_errors in form.errors.as_data.items %}
{{ key }}
{% for error in key_errors %}
{% if error.code == 'inactive_account'%}
// do some stuff
{% endif %}
{% endfor %}
{% endfor %}
There's also other way to check for the error code.
You can use has_error to check for the error code.
{% form.has_error 'field_name' 'code' %}
To check for non-field errors use NON_FIELD_ERRORS as the field parameter.

Read a file in django and find string in file

i am a new to django, and i'm trying to execute a django code in an html template, but it is showing the same error and i dont know how to make it work. I am trying to read some files and find the one that contains the string. This is the code in the template:
{% if documents %}
<ul>
{% for document in documents %}
{% if 'TheString' in open('document.docfile.url').read() %}
<li>{{ document.docfile.name }}</li>
{% else %}
<li></li>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p>No documents available.</p>
{% endif %}
The error is the following:
TemplateSyntaxError at /subir/
Could not parse the remainder: '('document.docfile.url').read()' from 'open('document.docfile.url').read()'
What could it be, or am i doing it wrong? Thanks in advanced.
Your problem is you are trying to use Python code in the template, like your open() call.
Django templates don't work like that - you can only use a very limited set of syntax, and the syntax is not the same as Python.
Everything inside {{ }} and {% %} needs to be special Django template syntax, not Python code.
See the Django Template language documentation for the full details.
You can't use code like this in a template directly see the documentation for available template tags and filters. From what I can tell by the code you have posted in your view.py you'll need something like this:
docs=[]
for document in documents:
if 'TheString' in open('/path/to/document').read():
docs.append(document)
after passing docs to the template you could do this in the template:
{% for doc in docs %}
<li>{{ document.docfile.name }}</li>
{% empty %}
<p>No documents available.</p>
{% endfor %}
I'd need to look at what you are passing from the view to be sure of this, but I'd gladly assist in further help with further information if this doesn't help.

getting multiple paginator

If I include paginator, then its printing multiple paginator on same page. because I am including in forloop. How do I solve this problem? please help
----------------------
{% autopaginate recipes %}
{% for recipe in recipes %}
{{ forloop.counter }}
{% endfor %}
-----------
here is my full code.
{% with followers=current_user.get_profile.get_following.all %}
{% for follower in followers %}
{% with recipes=follower.recipe_set.all %}
{% for recipe in recipes %}
{{ forloop.counter }}
{% endfor %}
{% endwith %}
{% endfor %}
{% endwith %}
Result - > 1 2 3 1 2 3 ...... 50. It should be 53. So I can easily use paginator
thanks
the doc string in the setup.py file of django-pagination mentions the below,
Decide on a variable that you would like to paginate, and use the autopaginate tag on that variable before iterating over it. This
could take one of two forms (using the canonical object_list
as an example variable):
{% autopaginate object_list %}
This assumes that you would like to have the default 20 results per page. If you would like to specify your own amount of
results per page, you can specify that like so:
`{% autopaginate object_list 10 %}`
Note that this replaces object_list with the list for the current page, so you can iterate over the object_list like you normally would.
Now you want to display the current page and the available pages, so somewhere after having used autopaginate, use the paginate
inclusion tag:
{% paginate %}
This does not take any arguments, but does assume that you have already called autopaginate, so make sure to do so first.
That's it! You have now paginated object_list and given users of
the site a way to navigate between the different pages--all without
touching your views.
So, where are you using paginate tag after the autopaginate? You actually need not loop through recipes, autopaginate should do that for you wherever you call paginate.