Tech Incent
Django Django Form

How to render Django form individual fields manually?

render-django-form-fields-manually

We already know Django build-in system is pretty good for developers. Django forms have the developer-friendly build-in feature, Django provides several forms of rendering build-in methods. what was I discuss in the last post of how to create Django form. It’s just plain HTML form, no CSS, no javascript. and you can’t expect user-friendly UI without CSS and can’t expect a server-side well validate form without javascript. So Django is great for simple UI form, but I am talking about a beautiful user-friend, more controlled, form fields rendering Django template form.

. So in this article, I will show a Django form in which every field renders manually in the template.

Build a Django form scenarios

Create a django product form

Create forms.py file in product directory, and define ProductForm with four fields.

Note: STATUS used for status form status choices data.

from django import forms

class ProductForm(forms.Form):
    STATUS = (
        ('published', "Published"),
        ('pending', 'Pending'),
        ('rejected', 'Rejected'),
    )
    name = forms.CharField(max_length=250, help_text="Name max length 250, as helper text")
    description = forms.CharField(widget=forms.Textarea())
    status = forms.ChoiceField(choices=STATUS)
    is_active = forms.BooleanField()

Create a Django view for render form

In the meanwhile, create a product_form view which renders ProductForm,

from django.shortcuts import render, redirect, reverse
from .forms import ProductForm

def product_form(request):
    form = ProductForm(request.POST or None)
    if request.method == 'POST':
        if form.is_valid():
            instance = form.save(false)
            # do more action with data
            # return redirect success view
    context = {
        'form': form
    }
    return render(request, 'product/product_form.html', context)

After Creating the product_form view, don’t forget to map the URL,

from django.urls import path
from .views import product_form

urlpatterns = [
    path('form', product_form, name="product_form")
]

Bravo, we are successfully set up the Django form view. now we need one more requirement template file

Create template view and render form

In the product directory, create a product/product_form.html file, which renders Django form render in UI. Keep in mind I link bootstrap link in the head for beautiful UI.

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Product Form  | tech Incent</title>
        <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
        <style>
            .container {
              width: 100%;
              max-width: 768px;
              margin-left: auto;
              margin-right: auto;
          }
        </style>
    </head>
    <body>
        <div class="container">
            <h2>Product Form</h2>
            <form action="{% url 'product_form' %}" method="post">
                {% csrf_token %}
                {{ form.as_p }}
                <button type="submit">Submit</button>
            </form>
        </div>
    </body>
</html>
render-form-as-p
Form Render as_p method

Now you can see, this is not a pretty good UI and also not a controlled Form.

Let’s render form manually

<form action="{% url 'product_form' %}" method="post" novalidate>
                {% csrf_token %}
                <div class="mb-4">
                    <label for="{{ form.name.id_for_label }}" class="form-label">{{ form.name.label }}: </label>
                    <input name="{{ form.name.html_name }}" type="text" class="form-control" id="{{ form.name.id_for_label }}" required>
                    {% if form.name.help_text %}
                    <div class="form-text">{{ form.name.help_text }}</div>
                    {% endif %}
                    {% for error in form.name.errors %}
                    <div class="invalid-feedback d-block text-end">{{ error }}</div>
                    {% endfor %}
                </div>
                <div class="mb-4">
                    <label for="{{ form.description.id_for_label }}" class="form-label">{{ form.description.label }}: </label>
                    <textarea name="{{ form.description.html_name }}" class="form-control" id="{{ form.description.id_for_label }}"></textarea>
                </div>
                <div class="mb-4">
                      <label class="form-label" for="{{ form.status.id_for_label }}">
                          {{form.status.label}}
                      </label>
                    <select name="{{ form.status.html_name }}" value="{{ form.status.value }}" id="{{ form.status.id_for_label }}" class="form-select" >
                        {% for widget in form.status.subwidgets %}
                            {{ widget }}
                        {% endfor %}
                    </select>

                </div>
                <div class="mb-4">
                    <div class="form-check">
                      <input name="{{ form.is_active.name }}" checked="{{ form.is_active.value }}" id="{{ form.is_active.id_for_label }}" class="form-check-input" type="checkbox">
                      <label class="form-check-label" for="{{ form.is_active.id_for_label }}">
                          {{form.is_active.label}}
                      </label>
                    </div>
                </div>
                <button class="btn btn-success px-4" type="submit">Submit</button>
            </form>
render-form-manually
Render Fields manually

Description of all {{ field }} attributes

django-form-field-attributes
Name field attributes
  • {{ field.label }}
    Label attribute renders field label, e.g. Name, Description.
  • {{ field.label_tag }}
    label_tag attribute renders a whole appropriate label HTML tag with form’s label_suffix. default label_suffix is a colon: Exapmle:
    <label for=”id_name”>Name:</label>
  • {{ field.id_for_label }}
    The ID that will be used for this field (id_name, id_description in the example above). If you are constructing the label manually, you may want to use this in place of label_tag. It’s also useful, for example, if you have some inline JavaScript and want to avoid hardcoding the field’s ID.
  • {{ field.value }}
    The value of the field. e.g if status field default value: pending.
  • {{ field.html_name }}
    The name of the field that will be used in the input element’s name field. This takes the form prefix into account if it has been set. Example: Name
  • {{ field.help_text }}
    Any help text that has been associated with the field.
  • {{ field.errors }}
    Outputs a <ul class=”errorlist”> containing any validation errors corresponding to this field. You can customize the presentation of the errors with a {% for error in field.errors %} loop. In this case, each object in the loop is a string containing the error message.
  • {{ field.is_hidden }}
    This attribute is True if the form field is a hidden field and False otherwise. It’s not particularly useful as a template variable, but could be useful in conditional tests such as:{% if field.is_hidden %} {# Do something special #} {% endif %}
  • {{ field.field }}
    The Field instance from the form class that this BoundField wraps. You can use it to access Field attributes, e.g. {{ name.field.max_length }}
  • {{ field.as_text }}
    This will render HTML input tag, example: <input id=”id_description” name=”description” />
  • {{ field.as_textarea }}
    this will render HTML textarea tag, example:
    <textarea name=”name” cols=”40″ rows=”10″ required id=”id_name></textarea>
  • {{ field.subwidgets }}
    Above form example, you saw status CharField as a choice field that has choices data. In subwidgets attribute provide help to render a list of Option HTML tag. Example: <option value=”published”>Published</option>, <option value=”pending”>Pending</option>

Related posts

Django abstractuser with example

Sajal Mia

Explained Django inline formset factory with example?

Sajal Mia

How to delete file when models instance is delete or update in Django?

Sajal Mia

Understanding Django and django design principles

Tech Incent

How to create a virtual environment for Django?

Sajal Mia

How to work with django ajax requests ?

Sajal Mia