Django Formset field label in error messages - django

Is there a simple way to get the field label in an error message for a Django formset. I am able to do it in a normal form like so:
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ field.label }}: {{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
However, I'd like the same thing for the formset. The closest I've gotten is
{% if formset.errors %}
{% for dict in formset.errors %}
{% for field, error in dict.items %}
<div class="alert alert-danger">
<strong>{{ field }}: {{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% endfor %}
{% for error in formset.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
However, this gives me the field name (e.g. pub_date) instead of the label (e.g. Publication Date). Any help much appreciated!

I can't see a simple way to get from the field string to the field instance in a template, so you may have to iterate over forms and fields instead of formset.errors:
{% if formset.errors %}
{% for form in formset %}
{% for field in form %}
{% if field.errors %}
<div class="alert alert-danger">
<strong>{{ field.label }}: {{ field.errors|escape }}</strong>
</div>
{% endif %}
{% endfor %}
{% endfor %}
{% for error in formset.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}

Related

How do I change the Django form.errors display text?

I want to remove the circled bit from being displayed. How would I be able to do this?
{% if form.errors %}
<div class="alert alert-warning alert-dismissible fade show"
role="alert">
<p class="m-0">{{ form.errors }}</p>
<button type="button"
class="btn-close"
data-bs-dismiss="alert"
aria-label="Close">
</button>
</div>
{% endif %}
This always displays
property where the error is found
error message
error message ...
I want to remove the property where the error is found. How would I do this?
Django Form has two error handlers:
Form.errors are field errors. By default, a dict of key "field name" : value "field errors"
Form.non_field_errors are general errors that have no relation to a field name, mainly errors from the Form.clean(..) method.
So you are trying to do an anti-pattern and a distraction to the user experience. Therefore you can best achieve a better experience by mapping each field to its value without the need to render the field name in the error.
Form custom rendering will give you full access to the Form API, and allow you to display the error in the way you like without the default render, something like the following looping over form's fields:
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
By doing the above, you will also need to render the non_field errors, and the complete HTML tags will be as follows:
{{ form.non_field_errors }}
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
Django also offers manual render for each field something like the following:
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="{{ form.subject.id_for_label }}">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="{{ form.message.id_for_label }}">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="{{ form.sender.id_for_label }}">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="{{ form.cc_myself.id_for_label }}">CC yourself?</label>
{{ form.cc_myself }}
</div>
Choose the best fit for your needs.
There is still a hacky thing you can do which is not a best practice and will lead to conflicts between Field validation and non-field validation as follows Getting a list of errors in a Django form:
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% endif %}
In Django 4.0 or high
{% if form.errors %}
{% for error in form.errors.as_data.values %}
{% for data in error.0 %}
{{ data }}
{% endfor %}
{% endfor %}
{% endif %}

Django custom Auth form. How to show error messages

Another Django form question -.-
So, I have this form which works just fine, but it won't show any error messages. I'm pretty new to customising forms, so my question is that, do I need to specify anything else in order for my messages to show up?
Forms.py file
class UserLoginForm(AuthenticationForm):
error_css_class = "error"
def __init__(self,*args,**kwargs):
super(UserLoginForm, self).__init__(*args,**kwargs)
username = forms.CharField(widget=forms.TextInput(
attrs={'class': 'input','placeholder': 'Username','label':''}
))
password = forms.CharField(widget=forms.PasswordInput(
attrs={'class': 'input','placeholder': 'Password','label':''}
))
HTML File:
{%block content%}
<form class="form" method="POST">
{% csrf_token %}
<fieldset class="form-group text-center text-uppercase">
<h1 class="sign-in__header">Sign up</h1>
{% for field in form %}
<p>
{{ field }}
{{ field.help_text }}
</p>
{% endfor %}
</fieldset>
<div class="form-group">
<button class="submit" type="submit">Sign in</button>
</div>
{% for field in form %}
<div>{{ field.errors}}</div>
{% endfor %}
</div>
</form>
</div>
{%endblock content%}
If you remain on the same view when the form is not valid then in template you can access this errors by passing them to your view like this .
def View(request):
form = myForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/yourview/')
return render(request, 'template.html', {'form': form})
then in template
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
Try this:
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<p> {{ error }} </p>
{% endfor %}
{% endfor %}
{% endif %}

How to exclude specific field types in a template form loop

I am using django_widget_tweaks to loop over form fields:
{% for field in form.visible_fields %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
{% endfor %}
This displays a happy Bootstrap4 compliant interface, except when displaying fields like radio when I need to use a custom-control class not the form-control class.
How can I filter the form field loop to exclude radio inputs so I can write this code separately?
I need to understand how to filter the field loop and what the correct way to do this with the field type for radio is.

Django: formset errors without li / *

I am using a formset. formset.non_form_errors are displayed exactly the way I need it. However my field specific errors in for dict in formset.errors are always displayed inlcuding the <li> tag. I tried .as_text, however that just added a * (and removed the li). But I don't need the * either.
Anyone who can help me with that?
{% if formset.total_error_count %}
{% if formset.non_form_errors %}
{% for error in formset.non_form_errors %}
<div class="alert alert-warning" role="alert">
{{ error|escape }}
</div>
{% endfor %}
{% endif %}
{% for dict in formset.errors %}
{% for error in dict.values %}
<div class="alert alert-warning" role="alert">
{{ error|escape }}
</div>
{% endfor %}
{% endfor %}
{% endif %}
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
The problem could be fixed by moving the individual errors in the form loop:
{% if formset.total_error_count %}
{% if formset.non_form_errors %}
{% for error in formset.non_form_errors %}
<div class="alert alert-warning" role="alert">
{{ error|escape }}
</div>
{% endfor %}
{% endif %}
{% endif %}
{% for form in formset %}
{% if form.quantity.errors %}
<div class="alert alert-warning" role="alert">
{% for error in form.quantity.errors %}
{{ error|escape }}
{% endfor %}
</div>
{% endif %}

Django: how to use a template tag as an arguments for another template tag

I need to use a template tag inside another tag that is a custom tag and it gives me this error:
Could not parse the remainder: '{{message.tags}}' from '{{message.tags}}'
How can I fix this? TIA for any help!
template.html:
<div class="bootstrap-iso">
{% if messages %}
<div class="messages ">
{% for message in messages %}
<div {% if message.tags %} class="alert {{ message.tags }} alert-dismissible" role="alert" {% endif %}>
<strong> {% get_message_print_tag {{message.tags}} %}: </strong>
{{ message }}
×
</div>
{% endfor %}
</div>
{% endif %}
</div>
If you are using template tags in delemeters "{% %}" you don't have to use "{{}}".
<div class="bootstrap-iso">
{% if messages %}
<div class="messages ">
{% for message in messages %}
<div {% if message.tags %} class="alert {{ message.tags }} alert-dismissible" role="alert" {% endif %}>
<strong> {% get_message_print_tag message.tags %}: </strong>
{{ message }}
×
</div>
{% endfor %}
</div>
{% endif %}
</div>
hope this will work.