{{ form.non_field_errors }} with django-crispy-forms - django

I have the following django form using crispy-forms:
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">TEAM SELECTION</h2>
</div>
<div class="panel-body">
<form action="" method="post">
{% csrf_token %}
<div>{{ form.non_field_errors }}</div>
<div class="col-xs-12 col-sm-5 col-md-5 col-lg-5">{{ form.team1|as_crispy_field }}</div>
<div class="col-xs-12 col-sm-5 col-md-5 col-lg-5">{{ form.team2|as_crispy_field }}</div>
<div class="col-xs-12 col-sm-2 col-md-2 col-lg-2"><button type="submit" class="btn btn-primary btn-block"; margin-bottom: 2cm;>Submit</button></div>
</form>
</div>
</div>
Everything looks amazing except the {{ form.non_field_errors }} part. It just looks like a bullet list as follows:
You picked the same team!
Does anyone know how I can have make the {{ form.non_field_errors }} look as exciting as the rest of the form?

Try the as_crispy_errors filter:
{% load crispy_forms_tags %}
{{ form|as_crispy_errors }}

Related

How to display error message with Django forms?

I would like to customize the Django login authentication form. The original form looks like this and it works perfectly:
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4 ">Log In</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Login</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">
Need An Account? <a class="ml-2" href="{% url 'register' %}">Sign Up Now</a>
</small>
</div>
</div>
{% endblock content %}
My goal is to modify the form style so that I can place the objects wherever I want. I was able to achieve this for the username and password fields, however I cannot display the error message just like in the original format.
This is what I tried:
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4 ">Log In</legend>
{% if formset.non_form_errors %}
<div class="alert alert-block alert-danger">
{% if formset_error_title %}<h4 class="alert-heading">{{ formset_error_title }}</h4>{% endif %}
<ul class="m-0">
{{ formset.non_form_errors|unordered_list }}
</ul>
</div>
{% endif %}
<div class="row">
<div class="col-md-4 col-sm-12 register-field">
{{ form.username|as_crispy_field }}
</div>
<div class="col-sm-12 register-field">
{{ form.password|as_crispy_field }}
</div>
</div>
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Login</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">
Need An Account? <a class="ml-2" href="{% url 'register' %}">Sign Up Now</a>
</small>
</div>
</div>
{% endblock content %}
Basically I saw that crispy uses a object called formset.non_form_errorshowever it looks like it is not working when I insert an invalid username/password.
Would you be able to suggest a smart and elegant way to achieve my goal please? This is what it should look like:
I was able to achieve my goal with this trick:
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4 ">Log In</legend>
<div class="row">
<!-- Added this new rows -->
{% if form.errors %}
<div class="col-12 register-field">
<div class="alert alert-block alert-danger">
<ul>
<li>Please enter a correct username and password. Note that both fields may be
case-sensitive.
</li>
</ul>
</div>
</div>
{% endif %}
<!-- ------------------- -->
<div class="col-md-4 col-sm-12 register-field">
{{ form.username|as_crispy_field }}
</div>
<div class="col-sm-12 register-field">
{{ form.password|as_crispy_field }}
</div>
</div>
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Login</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">
Need An Account? <a class="ml-2" href="{% url 'register' %}">Sign Up Now</a>
</small>
</div>
</div>
{% endblock content %}
Basically I check if there are any errors and then I create a div with the custom error message.

Django - How to apply onlivechange on CharField / IntegerField

I want to hide the field form.name_of_parent_if_minor if the age (CharField) < 18 else show. I am not getting where to write jQuery or JS code or add separate js file. For this do I need to the html definition and add tag for age (CharField) or we can perform action on this as well.
I am new to the Django so if you find any mistakes in my code then any help would be appreciated for guidance.
forms.py
class StudentDetailsForm(forms.ModelForm):
class Meta:
model = StudentDetails
views.py
class StudentCreateView(LoginRequiredMixin, CreateView):
template_name = 'student/student_details_form.html'
model = StudentDetails
form_class = StudentDetailsForm
success_url = "/"
html
{% extends 'student/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div id="idParentAccordian" class="content-section">
<form method="POST">
{% csrf_token %}
<div class="card mt-3">
<div class="card-header">
<a class="collapsed card-link" style="display: block;" data-toggle="collapse"
href="#idPersonalInformation">Personal Information</a>
</div>
<div id="idPersonalInformation" class="collapse show" data-parent="#idParentAccordian">
<div class="card-body">
<div class="row">
<div class="col-6">
{{ form.joining_date|as_crispy_field }}
</div>
<div class="col-6">
{{ form.class|as_crispy_field }}
</div>
</div>
{{ form.student_name|as_crispy_field }}
{{ form.father_name|as_crispy_field }}
{{ form.mother_name|as_crispy_field }}
{{ form.gender|as_crispy_field }}
<div class="row">
<div class="col-6">
{{ form.date_of_birth|as_crispy_field }}
</div>
<div class="col-6">
{{ form.age|as_crispy_field }}
</div>
</div>
<div>
{{ form.name_of_parent_if_minor|as_crispy_field }}
</div>
</div>
</div>
</div>
<div class="form-group mt-3">
<button class="btn btn-outline-info" type="submit">Save</button>
<a class="btn btn-outline-secondary" href="javascript:history.go(-1)">Cancel</a>
</div>
</form>
</div>
{% endblock content %}
the easiest way but not the cleanest is to add JS script in your html
the recommanded way is to add static folder to your app and load static files in your html template using {% load static %}

Sort by ascending and descending using django-filter

I have the following code for few filterings:
from .models import ProductLaptop
import django_filters
class ProductLaptopFilter(django_filters.FilterSet):
laptops_name = django_filters.CharFilter(lookup_expr='icontains')
laptops_price = django_filters.NumberFilter()
laptops_price__gt = django_filters.NumberFilter(field_name='laptops_price', lookup_expr='gt')
laptops_price__lt = django_filters.NumberFilter(field_name='laptops_price', lookup_expr='lt')
class Meta:
model = ProductLaptop
fields = ['laptops_name', 'laptops_price', 'brand_name']
The html codes for this:
{% load widget_tweaks %}
{% block content %}
<form method="get">
<div class="well">
<h4 style="margin-top: 0">Filter</h4>
<div class="row">
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_name.label_tag }}
{% render_field filter.form.laptops_name class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_price.label_tag }}
{% render_field filter.form.laptops_price class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.brand_name.label_tag }}
{% render_field filter.form.brand_name class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_price__gt.label_tag }}
{% render_field filter.form.laptops_price__gt class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_price__lt.label_tag }}
{% render_field filter.form.laptops_price__lt class="form-control" %}
</div>
</div>
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</div>
</form>
Which gives me a view like below:
Here I want to add an option where people can sort the items in ascending and descending order.
Can anyone give me some suggestions how can I implement this?
For that, you can use OrderingFilter from django-filter. Create this filter in your FilterSet class and provide all fields that should be enabled for ordering.

styling form render in Django

I'm using Django 2.x
I'm using Formset to be able to add multiple records at one.
the form is rendered in template file as
{{ chapter_questions.as_table }}
Which renders template like below which looks ugly.
I'm using Bootstrap template to design my template to look like
To render template like second image, I'm writing the fields manually as
<div class="form-group">
<div class="col-sm-12 col-xs-12">
<label for="question">Word</label>
<input name="chapterquestion_set-0-word" type="text" class="form-control border-color-2" placeholder="Word" id="question">
{% if chapterquestion_set.word.errors %}
<div class="row">
<div class="col-sm-12">
<div class="alert alert-danger">
<ul>
{% for error in chapter_questions.word.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}
</div>
<div class="col-sm-12 col-xs-12">
<label for="definition">Definition</label>
<input name="chapterquestion_set-0-definition" type="text" class="form-control border-color-3" placeholder="Definition" id="definition">
{% if chapter_questions.definition.errors %}
<div class="row">
<div class="col-sm-12">
<div class="alert alert-danger">
<ul>
{% for error in chapter_questions.definition.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}
</div>
<div class="col-sm-12 col-xs-12">
<label for="audio"></label>
<input name="chapterquestion_set-0-audio" type="text" class="form-control border-color-4" placeholder="Audio" id="audio">
{% if chapter_questions.audio.errors %}
<div class="row">
<div class="col-sm-12">
<div class="alert alert-danger">
<ul>
{% for error in chapter_questions.audio.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}
</div>
</div>
This way I have to write the code multiple times for multiple objects. Also for adding a new object fields, I need to replicate whole code using JavaScript by replacing index number (0 in this case) by updating by 1.
How can I style the form widget so that I could take benefit of Django automatic field insertions and error display and only need {{ chapter_questions.as_bootstrap_div }} to render bootstrap form.
templates/fields/text-field.html
<div class="col-sm-12 col-xs-12">
{{field.label_tag}}
<input name="{{field.name}}" type="text" class="form-control border-color-2" placeholder="{{field.label}}" id="{{field.name}}">
{% if field.errors %}
<div class="row">
<div class="col-sm-12">
<div class="alert alert-danger">
<ul>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}
</div>
on your form
{% with chapterquestion_set.word as field %}
{% include 'fields/text-field.html' %}
{% endwith %}

Detect active tab using Jinja2?

I'm making a Flask Webapp and I have the following tab content:
<div class="tab-content">
<div class="tab-pane fade in active" id="gable">
{% include 'building_form.html' %}
</div>
<div class="tab-pane fade" id="shed">
{% include 'building_form.html' %}
</div>
<div class="tab-pane fade" id="flat">
{% include 'building_form.html' %}
</div>
</div>
The code for building_form.html is:
<form method="post" action="">
{{ form.hidden_tag() }}
<div class="form-group label-floating">
{{ wtf.form_field(form.width) }}<br>
</div>
<div class="form-group label-floating">
{{ wtf.form_field(form.length) }}<br>
</div>
<div class="form-group label-floating">
{{ wtf.form_field(form.bottom_height) }}<br>
</div>
<div class="form-group label-floating">
{{ wtf.form_field(form.top_height) }}<br>
</div>
{% if ???? %} <!--What put here?-->
<div class="form-group label-floating">
{{ wtf.form_field(form.ridge_height) }}<br>
</div>
{% endif %}
<p><input type=submit value="Calcular"></p>
</form>
I´m only want to render the "form.ridge_height" when id="gable" is active. It is posible to do it using Jinja2?
You could do something like the below, it may not work out of the box though! You can pass variables into includes when they're wrapped using with. You may need to set up another CSS class called hidden if you haven't got one already, which can be done like this:
.hidden {
display: none;
}
{% with gable = True %}
{% include 'building_form.html' %}
{% endwith %}
And then within the building_form:
<div class="form-group label-floating {{ '' if gable == True else 'hidden' }}">
{{ wtf.form_field(form.ridge_height) }}<br>
</div>