Manually rendering form elements with custom CSS

Hi all.
I am porting a Flask application to Django and in the process getting familiar with the framework.

I have created a form with some input field, checkboxes etc. When rendering the form I would like to add a CSS class to a field if there were errors when submitting the form.

From my research I noticed that Django does not make this easy. All the suggestions and answers I found point to creating custom form elements, custom template, rendering logic etc to achieve this simple task.

In the documentation I also saw that Django gives you access to the individual elements so you can render them but it doesn’t proved all the information like for example if a checkbox is checked.

What are the different ways to manually render and customize forms? I prefer that styling stays in the HTML page rather than in python code.


Actually, this is part of base Django. See Rendering form error messages

It depends upon what you mean by “styling”. The css classes are typically and conventionally defined in .css files. However, the assignment of those classes to dynamic elements is handled by the view, since that’s where those elements are created.

Keep in mind that in Django (unlike some other frameworks), your html templates are not “first class” objects. Django’s focus is on the view. The template is just data being used to help render a page.

That’s really valuable information which I wasn’t able to find in other answers, thank you.

Perhaps some code examples will help me illustrate what I am struggling with.
Here is a code snippet of a form field that represents an input box that I am rendering manually.

<div class="mb-3">
    <label class="form-label" for="{{ form.price.id_for_label }}">Price</label>
    <input class="form-control{% if form.price.errors %} is-invalid{% endif %}" id="{{ form.price.id_for_label }}"
        name="{{ }}" type="text" value="{% if form.price.value %}{{ form.price.value }}{% endif %}">
    {% if form.price.errors %}
    <span class="invalid-feedback">
        {% for error in form.price.errors %}
        {{ error }}
        {% endfor %}
    {% endif %}

If you ignore most of the attributes in the input tag and focus on the class you’ll see that I have the following piece of code: {% if form.price.errors %} is-invalid{% endif %}. This controls the special styling of the input field when there is an error. I am using bootstrap and its form validation styling.

Bellow that you will see that I am actually using the errors provided by Django’s validation.

What I wondering is if there is a way to add the class in a straightforward way based on a condition (form field is invalid) instead of manually rendering the filed with all its attributes. From what I found, doing so outside the template require an unreasonable amount of code and effort so I am thinking I haven’t found the correct way of doing it.

Without being a lot more familiar with the whole template and other fields you may be rendering - along with the form being rendered and the view that is rendering the form, it would be difficult for me to suggest any specific alternative.

But I would suspect that since you can override any of form, widget, or field templates, along with setting attributes for those templates, there likely would be an easier way to handle this.
For example, see Syling required or erroneous form rows for one option.

Side note: If you’re bringing this forward from an older project, or are working from some older references, Django 4.x has added a lot of flexibility in how forms are rendered.

1 Like

I hadn’t seen that, thank you.

I think for now this is enough information for me to continue. I’ll see if I can do this the “Django” way and drop my old Flask habits. I just wanted to check if I am missing some pattern or way of doing things.

Thank you for the help, it was quite valuable!