How to show validation errors in template using CreateView Django - django

I am using an extended User model and a generic CreateView.
class SignUp(CreateView):
form_class = forms.SignUpForm
success_url = '/accounts/login/'
template_name = 'accounts/signup.html'
How do I access the form validation errors in my template? They must be there because when I do {{ form.as_p }} the errors show up. I have tried {{ form.errors }} and {{ field.errors }} but there is nothing in them. Is there a simple tag I can call in my template to show the errors? Thanks.

you can do it manually if you like. Each field is available as an attribute of the form using {{ form.name_of_field }}, and in a Django template, will be rendered appropriately. For example:
{{ 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>
and if you want to loop all errors once on the top page.
{% if form.non_field_errors %}
<ul>
{% for error in form.non_field_errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
If you’re using the same HTML for each of your form fields, you can reduce duplicate code by looping through each field in turn using a {% for %} loop:
{% 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 %}
you can check many methods to do that in Django documentation in the below URL
https://docs.djangoproject.com/en/4.0/topics/forms/#looping-over-the-form-s-fields

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 %}

How to render form.errors without html tag

i want to render form.errors individually without the html tag but it doesn't seem to work
views.py
....
context = {
'login_error': form.errors,
'login_form': LoginForm(),
}
return render(request, 'shop/login.html', context)
....
login.html
....
<label class="mt-1"> {{ login_form.username.label }} </label>
{{ login_form.username }}
{{ login_error.username }}
<label class="mt-1"> {{ login_form.password.label }} </label>
{{ login_form.password }}
{{ login_error.password }}
....
the answer i got is by unpacking it in a loop and then add an |escape
....
{% for error in login_error %}
{{ error|escape }}
{% endfor %}
<label class="mt-1"> {{ login_form.username.label }} </label>
{{ login_form.username }}
<label class="mt-1"> {{ login_form.password.label }} </label>
{{ login_form.password }}
....
so, the question is, why does this output with html tag
{{ login_error.username|escape }}
{{ login_error.password|escape }}
but this one output without html tag which is basically the same (?) as the above
{% for error in login_error %}
{{ error|escape }}
{% endfor %}
the expected outcome is the field error without html tag, but {{ login_error.username|escape }} also outputs the html tag
{% for error in login_error %}
{{ error|escape }}
{% endfor %}
outputs with no html tag but a loop is needed, i need to output errors individually but without the html tag

Flask WTForms - how to skip validation on fields in invisible div?

I have created a WTform in Python Flask, where I have a delivery form. If customer's billing address is different from delivery address then i am enabling div which contains fields for billing address. I am doing hiding and showing of div via jquery.
Originally i had all the fields in one Flaskform, but then i thought if i put billing fields in separate FlaskForm, and handle form.validate_on_submit() separately for 2nd form then may be i can skip validation for fields in Billing div.
But no, it is still performing validation on those fields, and because of that I am not able to move forward. If user has same addresses then billing fields will be empty and can't pass validation.
I am sure people must have encountered this situation but i can't find any answer regarding this.
Could someone guide me?
I am attaching code, to explain myself.
My Forms.py
class DeliveryForm(FlaskForm):
choices_billadd = [('1', 'Use delivery address'), ('2', 'Add a billing address')]
addressline1 = StringField('Address Line 1*',
validators=[DataRequired(), Length(min=1, max=100)])
addressline2 = StringField('Address Line 2',
validators=[Length(max=100)])
city = StringField('City*',
validators=[DataRequired(), Length(min=2, max=50)])
postcode = StringField('Postcode*',
validators=[DataRequired(), Length(min=2, max=50)])
billingaddress = SelectField('Billing Address*', choices = choices_billadd, validators = [DataRequired()])
submit = SubmitField('Submit')
class BillingForm(FlaskForm):
bill_addressline1 = StringField('Address Line 1*',
validators=[DataRequired(), Length(min=1, max=100)])
bill_addressline2 = StringField('Address Line 2',
validators=[Length(max=100)])
bill_city = StringField('City*',
validators=[DataRequired(), Length(min=2, max=50)])
bill_postcode = StringField('Postcode*',
validators=[DataRequired(), Length(min=2, max=50)])
<form method="POST" action="">
{{ form.csrf_token(id='login_csrf') }}
<fieldset class="form-group content-section">
<div class="row pt-3">
<div class="col-6">
{{ form.addressline1.label(class="form-control-label") }}
{% if form.addressline1.errors %}
{{ form.addressline1(class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.addressline1.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.addressline1(class="form-control") }}
{% endif %}
</div>
<div class="col-6">
{{ form.addressline2.label(class="form-control-label") }}
{% if form.addressline2.errors %}
{{ form.addressline2(class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.addressline2.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.addressline2(class="form-control") }}
{% endif %}
</div>
</div>
<div class="row pt-3">
<div class="col-6">
{{ form.city.label(class="form-control-label") }}
{% if form.city.errors %}
{{ form.city(class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.city.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.city(class="form-control") }}
{% endif %}
</div>
<div class="col-6">
{{ form.postcode.label(class="form-control-label") }}
{% if form.postcode.errors %}
{{ form.postcode(class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.postcode.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.postcode(class="form-control") }}
{% endif %}
</div>
</div>
<div class="row pt-3">
<div class="col-12">
{{ form.billingaddress.label(class="form-control-label") }}
{{ form.billingaddress(class="form-control") }}
</div>
</div>
<div id="div_billingaddress" class="">
<div class="row pt-3">
<div class="col-6">
{{ form_bill.bill_addressline1.label(class="form-control-label") }}
{% if form_bill.bill_addressline1.errors %}
{{ form_bill.bill_addressline1(class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form_bill.bill_addressline1.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form_bill.bill_addressline1(class="form-control") }}
{% endif %}
</div>
<div class="col-6">
{{ form_bill.bill_addressline2.label(class="form-control-label") }}
{% if form_bill.bill_addressline2.errors %}
{{ form_bill.bill_addressline2(class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form_bill.bill_addressline2.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form_bill.bill_addressline2(class="form-control") }}
{% endif %}
</div>
</div>
<div class="row pt-3">
<div class="col-6">
{{ form_bill.bill_city.label(class="form-control-label") }}
{% if form_bill.bill_city.errors %}
{{ form_bill.bill_city(class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form_bill.bill_city.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form_bill.bill_city(class="form-control") }}
{% endif %}
</div>
<div class="col-6">
{{ form_bill.bill_postcode.label(class="form-control-label") }}
{% if form_bill.bill_postcode.errors %}
{{ form_bill.bill_postcode(class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form_bill.bill_postcode.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form_bill.bill_postcode(class="form-control") }}
{% endif %}
</div>
</div>
</div>
</fieldset>
<div class="row py-4">
<div class="col-12">
{{ form.submit(class="btn btn-success btn-block") }}
</div>
</div>
</form>

How can I modify the class for a button in a django widget form?

I'm trying to set the class for a form widget. I have:
<form action="{% url "list" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.input.label_tag }} {{ form.input.help_text }}</p>
<p>
{{ form.input.errors }}
{{ form.input }}
</p>
<p>{{ form.non_field_errors }}</p>
<p>{{ form.itinerary.label_tag }} {{ form.itinerary.help_text }}</p>
<p>
{{ form.itinerary.errors }}
{{ form.itinerary }}
</p>
<p><input class="button-primary" type="submit" value="Upload" /></p>
</form>
and it looks like
I attempted to use django tweak tools when I tried googling to find a solution for my problem. I modified the code to be like this too see how it would change:
<form action="{% url "list" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% load widget_tweaks %}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.input.label_tag }} {{ form.input.help_text }}</p>
<p>
{{ form.input.errors }}
{{ form.input }}
{% render_field form.input class="button" %}
</p>
<p>{{ form.non_field_errors }}</p>
<p>{{ form.itinerary.label_tag }} {{ form.itinerary.help_text }}</p>
<p>
{{ form.itinerary.errors }}
{{ form.itinerary }}
</p>
<p><input class="button-primary" type="submit" value="Upload" /></p>
</form>
and that looks like
It applies the class to the whole widget, and it turns the whole widget into a button.
So how can I apply the class to just the button in the widget?
So there really isn't an easy way to add a class to a form element.
The way I was able to solve this was to create a custom template tag.
If you interested in learning more about this you can visit the following link: https://docs.djangoproject.com/en/1.7/howto/custom-template-tags/
What I did was create a directory under the app directory called templatetags.
Make sure you have an __init__.py in this directory, and then create another file. I named mine template_helper.py
# template_helper.py
from django import template
from django.utils.datastructures import SortedDict
register = template.Library()
#register.filter(name='addcss')
def addcss(field, css):
return field.as_widget(attrs={"class":css})
In the actual template you would just have to first load the template_helper via: {% load template_helper %} then add the {{ form_element|addcss:"button" }}
You'll want to somehow check with the template tags {% if ... %} to
make sure you only apply the class to the button if you only want to
apply the class to the button.
{% load template_helper %}
<form action="{% url "list" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.input.label_tag }} {{ form.input.help_text }}</p>
<p>
{{ form.input.errors }}
{% for field in form.input %}
{{ field|addcss:"button" }}
{% endfor %}
</p>
<p>{{ form.non_field_errors }}</p>
<p>{{ form.itinerary.label_tag }} {{ form.itinerary.help_text }}</p>
<p>
{{ form.itinerary.errors }}
{{ form.itinerary }}
</p>
<p><input class="button-primary" type="submit" value="Upload" /></p>
</form>
Good Luck!

Add unique styling to one form in a Django formset

I have a formset with four forms, and want to render the fourth one with different CSS from the others - unique color, styling, etc. Can I do this from my html page, or somewhere else?
I'm looking for something like this pseudo-code:
<form action="" method="post">{% csrf_token %}
{{ formset.management_form }}
{{ formset.non_form_errors }}
<div>
{% for form in formset except the last form %}
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
{% endfor %}
{% endfor %}
{% for the last form in the formset %}
{% for field in form %}
{{ field.errors }}
<div class="different style">
{{ field.label_tag }}:
<p class="another different style">{{ field }}</p>
</div>
{% endfor %}
{% endfor %}
</div>
<p><input type="submit" value="Submit" /></p>
</form>
See forloop.last in documentation -
<form action="" method="post">{% csrf_token %}
{{ formset.management_form }}
{{ formset.non_form_errors }}
<div>
{% for form in formset %}
{% if forloop.last %}
{% for field in form %}
{{ field.errors }}
<div class="different style">
{{ field.label_tag }}:
<p class="another different style">{{ field }}</p>
</div>
{% endfor %}
{% else %}
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
{% endfor %}
{% endif %}
</div>
<p><input type="submit" value="Submit" /></p>
</form>