Django check form error code in template - django

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.

Related

How to acess form based on index django

I am trying to access the form based on the index value how can i do that exactly?
Ex:
{% for line in data_lines %}
{{line}}
{% with x=forloop.counter %}
{{form.x}}
{% endwith %}
{% endfor %}
As Django discourages adding too much logic hence I don't think it's possible using built-in Django Template features. You can achieve this by sending a dict instead of data_lines and accessing via key, value as:
{% for key, value in data_lines.items %}
{{value}}
{{ form.key }}
{% endfor %}
If you really want it then you could write a custom template filter.

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.

Control the form errors display while using {{ form.as_ul }} in Django templates.

I like the convenient output form method {{ form.as_ul }} but is there a way I can still continue to use it but capture all the errors upfront instead of displaying the error just above each field.
I understand that there are ways to loop through each form element and so on as mentioned in django docs but I want to continue to utilize the capability of form.as_ul() except get control over error display.
Solved this problem by using Reusable Form Templates.
Its simple...
Create a reusable template with the following code snippets based on your need.
If you want to display all errors right at the top of the form...
{% if form %}
{% if form.errors %}
{% for field in form %}
{{field.errors}}
{% endfor %}
{% endif %}
{% for field in form %}
<li>{{ field.label_tag }}: {{ field }}</li>
{% endfor %}
{% endif %}
If you want to display all errors right after each form field without the default html elements around error use...
{% for field in form %}
{{ field.label_tag }}: {{ field }}
{% for error in field.errors %}{{ error }}{% endfor %}
{% endfor %}
Used the second template and created a Inclusion Tag
The only way I see is to inherit the new form class from forms.Form and alter as_ul method as you like. Which isn't very good if you are going to use third-party forms like login form and so on (they won't have this method).
I think the best solution is to create your own inclusion tag and render form with it. It will be as short as as_ul ({% render_form form %}) but very flexible, it will work with all forms and won't mix HTML and Python code.
I still think the customization for rendering form in templates is quite flexible. I usually do this for my webapps. You may work with a bit javascript and css but not a big problem. Moreover, I think we should try to make the app simple.

Django Newbie ManyToManyField Template Question

I have a Django model with a ManyToManyField and I'm trying to iterate the contents of that field in a comma-delimited list in my template. I'm getting some unexpected results.
{% for painting in paintings_list %}
<p>{% for item in painting.style.all %}
{{ item.style|join:', ' }}
{% endfor %}</p>
{% endfor %}
The contents are being displayed as they exist in the database, but they're displayed in an unanticipated way...ie. instead of:
Renaissance, Baroque, Expressionist
I'm getting:
R,e,n,a,i,s,s,a,n,c,e,,B,a,r,o,q,u,e,,E,x,p,r,e,s,s,i,o,n,i,s,t
Any idea what I'm doing wrong? Would have thought the join template filter was for exactly this type of scenario, but perhaps the proper way to do this would be to create a custom method of the model...
Ignacio Vasquez-Abrams is correct (as usual). A solution to your problem might lie in the forloop variables.
<p>{% for item in painting.style.all %}
{{item.style}} {% if not forloop.last %}, {% endif %}
{% endfor %}</p>
item.style is returning a string, so you're joining each character with , instead of each item.

Django: Displaying formset errors correctly

I have an inline formset for a model, which has a unique_together constraint. And so, when I input data, which doesn't fulfill this constraint, it displays:
__all__Please correct the duplicate values below.
The code, which does this is:
{% for error in formset.errors %}
{{ error }}<br/>
{% endfor %}
I don't much like the __all__ at the beginning of the error and it is quite clearly the dictionary key, so I tried:
{% for key, error in formset.errors %}
{{ key }}: {{ error }}<br/>
{% endfor %}
But then all I get is:
__all__:
{{ error }} won't display at all. So what's going on here? And how do I display the error correctly?
I think the problem here is that formset.errors is a list of dictionaries, not a single dictionary.
From the Django docs page on formsets:
>>> formset.errors
[{}, {'pub_date': [u'This field is required.']}]
See if something like this fixes the problem: (Updated based on the askers comments)
{% for dict in formset.errors %}
{% for error in dict.values %}
{{ error }}
{% endfor %}
{% endfor %}
If that fails, I'd try using manage.py shell, and try to reproduce your situation in the python shell... that way it will be easy to inspect the various values and figure out what you need to do.
The for loops are unnecessary, these errors should be correctly displayed with the following:
{{ formset.non_form_errors }}
Here is a clarification for anyone encountering similar issues of errors not being rendered in template:
If you have and error regarding the formset as a whole, use:
{{ formset.non_form_errors }}
this basically returns errors in __all__ entry from formset.errors. It is documented as:
"""
Returns an ErrorList of errors that aren't associated with a particular
form -- i.e., from formset.clean(). Returns an empty ErrorList if there
are none.
"""
However if you are rendering forms from formset and some errors are not being renderd, you are probably missing:
{% for form in formset.forms %}
{# ... #}
{{ form.non_field_errors }}
{% endfor %}
this returns errors in __all__ entry from form.errors. Those are, analogous to the non_form_errors, the errors that aren't associated with a particular field, but rather with the field relations. For example if you had a form with fields From and To, and you validate if From value is smaller then To value, the tag {{ form.non_field_errors }} could render the following error:
'The From value must be smaller than the To value'
Django 1.6 formsets have a new method, BaseFormSet.total_error_count. Using this in a template conditional ensures you only will output errors and markup if at least one error exists in the formset.
{% if formset.total_error_count %}
<ul class="errorList">
{% for dict in formset.errors %}
{% for error in dict.values %}
<li>{{ error }}</li>
{% endfor %}
{% endfor %}
</ul>
{% endif %}
See the Django docs page for v1.6+.