{"id":119338,"date":"2024-11-26T09:51:44","date_gmt":"2024-11-26T09:51:44","guid":{"rendered":"\/tutorials\/?p=119338"},"modified":"2026-03-10T10:04:47","modified_gmt":"2026-03-10T10:04:47","slug":"django-forms","status":"publish","type":"post","link":"\/my\/tutorials\/django-forms","title":{"rendered":"How to use Django forms: Creating, rendering and handling forms"},"content":{"rendered":"<?xml encoding=\"utf-8\" ?><p>Django forms are Python classes that define the structure, validation rules, and rendering behavior of HTML forms in Django web applications. For example, the Form class lets you create a form with custom logic, while the ModelForm enables you to easily include fields in your web application based on a model.<\/p><p>Rendering forms is also straightforward with helper functions, which use pre-configured wrappers to display these fields. In terms of logic, you can handle form submissions and validation gracefully using a simple workflow involving <strong>request.POST<\/strong>,<strong> form.is_valid()<\/strong>, and the<strong> cleaned_data<\/strong> property.<\/p><p>Moreover, you can set error handling method easily using the default template variables, and even customize them for a more personalized notification. This allows you to give more details and personalize the error message, which helps improve user experience.<\/p><p>A distinguishing feature of Django is <strong>formset<\/strong>, which lets you manage them from a single page. Learn more about Django forms in more detail, including how to properly handle submissions and errors. <\/p><p>\n\n\n\n<\/p><h2 class=\"wp-block-heading\" id=\"h-how-to-create-django-forms\">How to create Django forms<\/h2><p>You can create forms in Django using two main methods: by using the <span style=\"margin: 0px;padding: 0px\"><strong>Form<\/strong>&nbsp;class to define fields manually or automatically generating<\/span> them from <a href=\"\/my\/tutorials\/django-models\">Django models<\/a> using <strong>ModelForm<\/strong>.<\/p><p>Use <strong>Form<\/strong> to define fields that don&rsquo;t directly relate to a model or need custom logic. Meanwhile, use <strong>ModelForm <\/strong>to create forms based on an existing model, which helps minimize boilerplate code and ensures schema consistency.<\/p><p>To create a form in Django, define a form class in your <strong>forms.py<\/strong> file. This class specifies the form fields and validation rules to effectively process user input.<\/p><h3 class=\"wp-block-heading\" id=\"h-creating-forms-manually-with-forms-form\">Creating forms manually with forms.Form<\/h3><p>Here&rsquo;s an example of creating a simple contact form manually:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># forms.py\nfrom django import forms\n\nclass ContactForm(forms.Form):\n    name = forms.CharField(max_length=100, label='Your Name')\n    email = forms.EmailField(label='Your Email')\n    message = forms.CharField(widget=forms.Textarea, label='Your Message')\n<\/pre><p>This form includes three fields: <strong>name<\/strong>, <strong>email<\/strong>, and <strong>message<\/strong>. Each field is defined using Django&rsquo;s form field classes:<\/p><ul class=\"wp-block-list\">\n<li><strong>CharField<\/strong> for short text inputs like the name.<\/li>\n\n\n\n<li><strong>EmailField<\/strong> for email validation.<\/li>\n\n\n\n<li><strong>CharField<\/strong> with a Textarea widget for longer text inputs, such as messages.<\/li>\n<\/ul><h3 class=\"wp-block-heading\" id=\"h-generating-forms-from-models-using-modelform\">Generating forms from models using ModelForm<\/h3><p>In many cases, forms are tied to models. Django simplifies this by letting you create forms directly from <a href=\"\/my\/tutorials\/django-models-and-databases\">models<\/a> using <strong>ModelForm<\/strong>. This saves time by automatically generating form fields based on the model&rsquo;s fields.<\/p><ol class=\"wp-block-list\">\n<li><strong>Creating a ModelForm form<\/strong>:<\/li>\n<\/ol><p>If you have a <strong>Post <\/strong>model in your <strong>models.py<\/strong> file:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># models.py\nfrom django.db import models\n\nclass Post(models.Model):\n    title = models.CharField(max_length=200)\n    content = models.TextField()\n    created_at = models.DateTimeField(auto_now_add=True)\n<\/pre><p>You can create a form for this model as follows:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># forms.py\nfrom django import forms\nfrom .models import Post\n\nclass PostForm(forms.ModelForm):\n    class Meta:\n        model = Post\n        fields = ['title', 'content']<\/pre><ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Using the ModelForm form in a view:<\/strong><\/li>\n<\/ol><p>Next, use the form in your <a href=\"\/my\/tutorials\/building-django-views\">Django view<\/a> like this:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># views.py\nfrom django.shortcuts import render\nfrom .forms import PostForm\n\ndef create_post(request):\n    if request.method == 'POST':\n        form = PostForm(request.POST)\n        if form.is_valid():\n            form.save()  # Saves the form data to the database\n            return redirect('post_list')  # Redirect to a list of posts\n    else:\n        form = PostForm()\n    return render(request, 'create_post.html', {'form': form})\n<\/pre><p>With <strong>ModelForm<\/strong>, Django automatically generates form fields based on the model&rsquo;s fields and handles saving the form to the database with minimal boilerplate code.<\/p><h2 class=\"wp-block-heading\" id=\"h-rendering-forms-in-django-templates\">Rendering forms in Django templates<\/h2><p>Once a form is created, it must be rendered in a template to collect user input. This step is crucial for user experience, providing the flexibility to choose between quick prototyping with Django&rsquo;s built-in shortcuts or full customization through manual rendering.<\/p><p>Django provides two approaches for rendering forms in templates: <strong>using built-in rendering shortcuts<\/strong> and <strong>manual rendering for full control<\/strong>.<\/p><h3 class=\"wp-block-heading\" id=\"h-simple-rendering-with-helper-functions\">Simple rendering with helper functions<\/h3><p>Django provides built-in rendering tools called helper functions. Since these functions are pre-configured, you don&rsquo;t need to write the HTML code to render forms in templates. This approach is suitable during prototyping because it&rsquo;s easier and more efficient than manual rendering. <\/p><p>While simple, using helper functions is less flexible since you can only use three methods to render a form with different structures:<\/p><ul class=\"wp-block-list\">\n<li><strong>form.as_p<\/strong> &ndash; wraps each form field in a <strong>&lt;p&gt;<\/strong> tag, ideal for quick and clean styling.<\/li>\n\n\n\n<li><strong>form.as_table<\/strong> &ndash; displays form fields in an HTML table, useful for structured layouts.<\/li>\n\n\n\n<li><strong>form.as_ul<\/strong> &ndash; wraps each field in <strong>&lt;li&gt;<\/strong> tags for list-style formatting.<\/li>\n<\/ul><p>Here&rsquo;s an example of using <strong>form.as_table<\/strong>:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;form method=\"post\"&gt;\n    {% csrf_token %}\n    {{ form.as_table }}\n    &lt;button type=\"submit\"&gt;Submit&lt;\/button&gt;\n&lt;\/form&gt;\n<\/pre><ul class=\"wp-block-list\">\n<li><strong>{% csrf_token %} <\/strong>&ndash; adds a CSRF token to protect against cross-site request forgery attacks. This is required for forms that use <strong>POST<\/strong> submission.<\/li>\n<\/ul><h3 class=\"wp-block-heading\" id=\"h-custom-rendering-with-html\">Custom rendering with HTML<\/h3><p>Custom rendering Django forms with HTML means manually writing the code to access and render the fields. This approach gives you complete control of the forms&rsquo; appearance and behavior, making it suitable if you want more in-depth customization. <\/p><p>The custom rendering approach is also ideal when you need to integrate forms into a custom-designed HTML structure or apply advanced CSS styling.<\/p><p>To select and access a Django form to render, use its field name (e.g. <strong>form.name<\/strong>). Below is an example of a full custom HTML layout that renders the <strong>form.name<\/strong> Django form:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;form method=\"post\" action=\"\/submit-form\/\"&gt;\n    {% csrf_token %}\n    &lt;div class=\"form-group\"&gt;\n        &lt;label for=\"id_name\"&gt;Name&lt;\/label&gt;\n        &lt;input type=\"text\" id=\"id_name\" name=\"name\" class=\"form-control\" value=\"{{ form.name.value|default:'' }}\"&gt;\n        {% for error in form.name.errors %}\n            &lt;div class=\"error\"&gt;{{ error }}&lt;\/div&gt;\n        {% endfor %}\n    &lt;\/div&gt;\n\n    &lt;div class=\"form-group\"&gt;\n        &lt;label for=\"id_email\"&gt;Email&lt;\/label&gt;\n        {{ form.email }}\n        {% for error in form.email.errors %}\n            &lt;div class=\"error\"&gt;{{ error }}&lt;\/div&gt;\n        {% endfor %}\n    &lt;\/div&gt;\n\n    &lt;div class=\"form-group\"&gt;\n        &lt;label for=\"id_message\"&gt;Message&lt;\/label&gt;\n        {{ form.message }}\n        {% for error in form.message.errors %}\n            &lt;div class=\"error\"&gt;{{ error }}&lt;\/div&gt;\n        {% endfor %}\n    &lt;\/div&gt;\n\n    &lt;button type=\"submit\" class=\"btn btn-primary\"&gt;Send Message&lt;\/button&gt;\n&lt;\/form&gt;\n<\/pre><p>You can use Django widgets to add CSS classes or attributes to form fields directly in your <strong>forms.py<\/strong>, for instance:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django import forms\n\nclass ContactForm(forms.Form):\n    name = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))\n    email = forms.EmailField(widget=forms.EmailInput(attrs={'class': 'form-control'}))\n    message = forms.CharField(widget=forms.Textarea(attrs={'class': 'form-control'}))\n<\/pre><p>Then, in your template:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;form method=\"post\"&gt;\n    {% csrf_token %}\n    {{ form.name }}\n    {{ form.email }}\n    {{ form.message }}\n    &lt;button type=\"submit\"&gt;Submit&lt;\/button&gt;\n&lt;\/form&gt;\n<\/pre><h2 class=\"wp-block-heading\" id=\"h-handling-form-submissions-in-django-views\">Handling form submissions in Django views<\/h2><p>When a user submits a form in Django, the data is sent to the view through an HTTP request. The form instance is then populated with that data and checked for validity. A typical submission workflow looks like this:<\/p><ul class=\"wp-block-list\">\n<li><strong>Form instance &rarr; populated with &rarr; request.POST<\/strong><\/li>\n\n\n\n<li><strong>form.is_valid() &rarr; returns &rarr; True\/False<\/strong><\/li>\n\n\n\n<li><strong>cleaned_data &rarr; provides &rarr; validated input<\/strong><\/li>\n<\/ul><p>If the form is valid, the cleaned data can be saved to the database using <strong>ModelForm.save()<\/strong> or passed to other parts of your application for processing.<\/p><p>Here&rsquo;s a simple example that shows a view handling a form submission:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.shortcuts import render\nfrom .forms import ContactForm\n\ndef contact_view(request):\n    if request.method == \"POST\":\n        form = ContactForm(request.POST)\n        if form.is_valid():\n            # Access validated input\n            name = form.cleaned_data[\"name\"]\n            email = form.cleaned_data[\"email\"]\n            message = form.cleaned_data[\"message\"]\n\n            # Here you could save data or trigger other logic\n            # Example: contact.save() if using a ModelForm\n\n            return render(request, \"success.html\")\n    else:\n        form = ContactForm()\n\n    return render(request, \"contact.html\", {\"form\": form})\n<\/pre><p>In this example:<\/p><ul class=\"wp-block-list\">\n<li><strong>request.POST<\/strong> passes submitted data to the form.<\/li>\n\n\n\n<li><strong>form.is_valid()<\/strong> runs Django&rsquo;s built-in and custom validation rules.<\/li>\n\n\n\n<li><strong>cleaned_data<\/strong> gives you access to the validated input.<\/li>\n<\/ul><p>This is where custom validation methods, like <strong>clean_name() i<\/strong>n the form class, come into play. They raise errors when rules are broken, and Django automatically links those errors to the form fields.<\/p><p>Forms in Django connect the pieces of your application: they take input from templates, validate and process it in views, and can save it directly to models. This makes them a central part of how data flows through a project.<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Current examples are correct but incomplete.\nAdd the workflow triple:\nForm instance &rarr; populated with &rarr; request.POST\nform.is_valid() &rarr; returns &rarr; True\/False\ncleaned_data &rarr; provides &rarr; validated input\nAdd a note that validated data can be saved to the DB (via ModelForm.save()) or processed otherwise.\nConnect to broader context: forms link models &harr; templates &harr; views\n<\/pre><h2 class=\"wp-block-heading\" id=\"h-validating-and-processing-forms\">Validating and processing forms<\/h2><p>Validation ensures that submitted data is both secure and reliable. Without it, users could send incomplete, malformed, or even malicious data. Django makes this process easier by providing automatic checks and letting you define your own rules when needed.<\/p><h3 class=\"wp-block-heading\">Built-in validation<\/h3><p>Django runs several checks as soon as a form is validated. Two of the most important are:<\/p><ul class=\"wp-block-list\">\n<li><strong>Required fields<\/strong>. Requiring all form fields to have input by default, unless explicitly set to&nbsp;<strong>required=False<\/strong>. This ensures critical fields are not left blank.<\/li>\n\n\n\n<li><strong>Field types<\/strong>. Validating input types based on the field definition. For example:\n<ul class=\"wp-block-list\">\n<li><strong>EmailField<\/strong>&nbsp;checks for a valid email address.<\/li>\n\n\n\n<li><strong>IntegerField<\/strong>&nbsp;ensures the input is a valid integer.<\/li>\n\n\n\n<li><strong>URLField<\/strong>&nbsp;validates that the input is a properly formatted URL.<\/li>\n<\/ul>\n<\/li>\n<\/ul><p>These checks happen automatically whenever you call <strong>form.is_valid() <\/strong>in your view.<\/p><h3 class=\"wp-block-heading\">Custom validation<\/h3><p>For more specific rules, Django lets you define your own validation logic. There are two main approaches:<\/p><ul class=\"wp-block-list\">\n<li><strong>Field-level validation<\/strong>. Using<strong> clean_&lt;fieldname&gt;()<\/strong> to set rules that apply to one field only. For example, you can block certain usernames like <strong>admin<\/strong> or <strong>test<\/strong>.<\/li>\n\n\n\n<li><strong>Form-level validation<\/strong>. Overriding the <strong>clean()<\/strong> method for rules that involve multiple fields. For example, you can enforce that a <strong>start date<\/strong> is earlier than an <strong>end date<\/strong>, or ensure that two fields together are unique.<\/li>\n<\/ul><p>Here&rsquo;s a simple example of field-level validation:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django import forms\nfrom django.core.exceptions import ValidationError\n\nclass ContactForm(forms.Form):\n    name = forms.CharField(max_length=100, label='Your Name')\n    email = forms.EmailField(label='Your Email')\n    message = forms.CharField(widget=forms.Textarea, label='Your Message')\n\n    def clean_name(self):\n        name = self.cleaned_data.get('name')\n        if \"spam\" in name.lower():\n            raise ValidationError(\"Invalid name: 'spam' is not allowed.\")\n        return name\n<\/pre><p>In this form, the <strong>clean_name() method<\/strong> runs <strong>field-level validation<\/strong>. Since it only checks the <strong>name field<\/strong>&lsquo;s value, putting the logic inside <strong>clean_name()<\/strong> is the most direct and efficient approach. If the input contains the word <em>spam<\/em> (case-insensitive), Django raises a <strong>ValidationError<\/strong>. The error is then automatically linked to the <strong>name field<\/strong> and displayed when the form is re-rendered.<\/p><p>This is an ideal application for field-level validation because the restriction applies to <strong>one specific field<\/strong>. You&rsquo;d use <strong>form-level validation<\/strong>, or <strong>clean()<\/strong>, when the rule depends on multiple fields together, such as when checking that a start date is earlier than an end date.<\/p><h2 class=\"wp-block-heading\" id=\"h-customizing-form-errors\">Customizing form errors<\/h2><p>Error handling in Django forms ensures users understand and fix mistakes quickly. By default, Django attaches error messages to form fields, but developers can customize both how errors are displayed in templates and what the messages say.<\/p><h3 class=\"wp-block-heading\">Default error messages<\/h3><p>Django forms generate default error messages whenever input fails validation. For example:<\/p><ul class=\"wp-block-list\">\n<li><strong>This field is required.<\/strong> Appears when a required field is left blank.<\/li>\n\n\n\n<li><strong>Enter a valid email address.<\/strong> Shows up when input doesn&rsquo;t match an email format.<\/li>\n\n\n\n<li><strong>Ensure this value has at most X characters.<\/strong> Displays when text exceeds <strong>max_length<\/strong> in <strong><strong>CharField<\/strong><\/strong>.<\/li>\n<\/ul><p>These defaults provide basic usability without extra configuration. You can display them in your templates like this:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;form method=\"post\"&gt;\n    {% csrf_token %}\n    &lt;div&gt;\n        {{ form.name.label_tag }} {{ form.name }}\n        {{ form.name.errors }}\n    &lt;\/div&gt;\n    &lt;div&gt;\n        {{ form.email.label_tag }} {{ form.email }}\n        {{ form.email.errors }}\n    &lt;\/div&gt;\n    &lt;div&gt;\n        {{ form.message.label_tag }} {{ form.message }}\n        {{ form.message.errors }}\n    &lt;\/div&gt;\n    &lt;button type=\"submit\"&gt;Send Message&lt;\/button&gt;\n&lt;\/form&gt;\n<\/pre><h3 class=\"wp-block-heading\">Customizing error display in templates<\/h3><p><strong>Developers <\/strong>can override the default messages with the <strong>error_messages <\/strong>parameter when defining fields in the form class. This is especially useful for providing user-friendly language or instructions tailored to your audience, which helps improve overall user experience.<\/p><p>In the following example, the default error <strong>This field is required<\/strong> is replaced with clearer, more conversational text. For instance, <strong>We need your email address to contact you<\/strong> gives users context and feels friendlier than the default. <\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django import forms\n\nclass ContactForm(forms.Form):\n    name = forms.CharField(\n        max_length=100,\n        error_messages={\n            'required': 'Please enter your name.',\n            'max_length': 'Name must not exceed 100 characters.'\n        }\n    )\n    email = forms.EmailField(\n        error_messages={\n            'required': 'We need your email address to contact you.',\n            'invalid': 'Please enter a valid email address.'\n        }\n    )\n    message = forms.CharField(\n        widget=forms.Textarea,\n        error_messages={'required': 'Don&rsquo;t forget to include a message!'}\n    )<\/pre><p>By default, error messages are rendered as plain text, but you can change their styling and placement. Django makes this possible by exposing errors for each field, so you can wrap them in your custom HTML:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;form method=\"post\"&gt;\n    {% csrf_token %}\n    &lt;div&gt;\n        {{ form.name.label_tag }} {{ form.name }}\n        {% if form.name.errors %}\n            &lt;div class=\"error\"&gt;{{ form.name.errors }}&lt;\/div&gt;\n        {% endif %}\n    &lt;\/div&gt;\n    &lt;div&gt;\n        {{ form.email.label_tag }} {{ form.email }}\n        {% if form.email.errors %}\n            &lt;div class=\"error\"&gt;{{ form.email.errors }}&lt;\/div&gt;\n        {% endif %}\n    &lt;\/div&gt;\n    &lt;div&gt;\n        {{ form.message.label_tag }} {{ form.message }}\n        {% if form.message.errors %}\n            &lt;div class=\"error\"&gt;{{ form.message.errors }}&lt;\/div&gt;\n        {% endif %}\n    &lt;\/div&gt;\n    &lt;button type=\"submit\"&gt;Send Message&lt;\/button&gt;\n&lt;\/form&gt;<\/pre><p>This approach ensures errors appear directly next to the relevant fields, improving clarity and accessibility.<\/p><h2 class=\"wp-block-heading\" id=\"h-using-django-formsets\">Using Django formsets<\/h2><p>Formsets in Django allow you to manage multiple form instances from a single page. This abstraction layer helps you create, validate, and process several forms together as a group, rather than handling each one separately.<\/p><p>Formsets  are useful for handling related data or dynamic forms, such as adding multiple entries to a database simultaneously. Django provides the <strong>formset_factory<\/strong> utility function to simplify the process of generating a formset class from any standard form class.<\/p><h3 class=\"wp-block-heading\" id=\"h-creating-a-formset\">Creating a formset<\/h3><p>To create a formset, define a base form in the <strong>forms.py <\/strong>file:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># forms.py\nfrom django import forms\n\nclass ItemForm(forms.Form):\n    name = forms.CharField(max_length=100)\n    quantity = forms.IntegerField(min_value=1)<\/pre><p>Then, generate a formset using <strong>formset_factory<\/strong> in <strong>views.py<\/strong>:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># views.py\nfrom django.shortcuts import render\nfrom django.forms import formset_factory\nfrom .forms import ItemForm\n\ndef manage_items(request):\n    ItemFormSet = formset_factory(ItemForm, extra=3)  # Create 3 empty forms by default\n    if request.method == \"POST\":\n        formset = ItemFormSet(request.POST)\n        if formset.is_valid():\n            for form in formset:\n                # Process each form's cleaned data\n                print(form.cleaned_data)\n            return redirect('success')  # Redirect after processing\n    else:\n        formset = ItemFormSet()\n    return render(request, 'manage_items.html', {'formset': formset})\n<\/pre><h3 class=\"wp-block-heading\" id=\"h-using-model-formsets\">Using model formsets<\/h3><p>The <strong>formset_factory<\/strong> utility will generate a formset from a standard form class. If you want to create a formset from a model, use Django&rsquo;s <strong>modelformset_factory<\/strong> instead:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.forms import modelformset_factory\nfrom .models import Item\n\ndef manage_items(request):\n    ItemFormSet = modelformset_factory(Item, fields=('name', 'quantity'), extra=3)\n    if request.method == \"POST\":\n        formset = ItemFormSet(request.POST)\n        if formset.is_valid():\n            formset.save()  # Save all forms at once\n            return redirect('success')\n    else:\n        formset = ItemFormSet()\n    return render(request, 'manage_items.html', {'formset': formset})<\/pre><h2 class=\"wp-block-heading\" id=\"h-what-s-next-after-learning-django-forms\">What&rsquo;s next after learning Django forms?<\/h2><p>Django forms simplify handling user input with built-in validation, customizable error messages, and rendering flexibility. This is one of the more advanced features of the Python framework that helps streamline your web application development. <\/p><p>After understanding how forms work, it&rsquo;s time to implement your knowledge by deploying a Django project. You can do this on a local development environment or using a remote system like Hostinger&rsquo;s VPS, which is more convenient and customizable.<\/p><p>Meanwhile, we recommend checking our <a href=\"\/my\/tutorials\/django-tutorial\">Django tutorial<\/a> if you want to learn about other important concepts and features of this Python framework.<\/p><?xml encoding=\"utf-8\" ?><figure class=\"wp-block-image size-large\"><a href=\"\/my\/vps-hosting\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" width=\"1024\" height=\"300\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2023\/02\/VPS-hosting-banner-1024x300.png\" alt=\"\" class=\"wp-image-77934\" srcset=\"https:\/\/www.hostinger.com\/my\/tutorials\/wp-content\/uploads\/sites\/45\/2023\/02\/VPS-hosting-banner.png 1024w, https:\/\/www.hostinger.com\/my\/tutorials\/wp-content\/uploads\/sites\/45\/2023\/02\/VPS-hosting-banner-300x88.png 300w, https:\/\/www.hostinger.com\/my\/tutorials\/wp-content\/uploads\/sites\/45\/2023\/02\/VPS-hosting-banner-150x44.png 150w, https:\/\/www.hostinger.com\/my\/tutorials\/wp-content\/uploads\/sites\/45\/2023\/02\/VPS-hosting-banner-768x225.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Django forms are Python classes that define the structure, validation rules, and rendering behavior of HTML forms in Django web applications. For example, the Form class lets you create a form with custom logic, while the ModelForm enables you to easily include fields in your web application based on a model. Rendering forms is also [&#8230;]<\/p>\n<p><a class=\"btn btn-secondary understrap-read-more-link\" href=\"\/my\/tutorials\/django-forms\">Read More&#8230;<\/a><\/p>\n","protected":false},"author":185,"featured_media":126622,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"How to use Django forms to easily build and manage forms","rank_math_description":"Learn how to build, validate, and customize Django forms, from basic form handling to advanced features like formsets and file uploads.","rank_math_focus_keyword":"django forms","footnotes":""},"categories":[22639],"tags":[],"class_list":["post-119338","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-vps"],"hreflangs":[{"locale":"en-US","link":"https:\/\/www.hostinger.com\/tutorials\/django-forms","default":0},{"locale":"en-UK","link":"https:\/\/www.hostinger.com\/uk\/tutorials\/django-forms","default":0},{"locale":"en-MY","link":"https:\/\/www.hostinger.com\/my\/tutorials\/django-forms","default":0},{"locale":"en-PH","link":"https:\/\/www.hostinger.com\/ph\/tutorials\/django-forms","default":0},{"locale":"en-IN","link":"https:\/\/www.hostinger.com\/in\/tutorials\/django-forms","default":0},{"locale":"en-CA","link":"https:\/\/www.hostinger.com\/ca\/tutorials\/django-forms","default":0},{"locale":"en-AU","link":"https:\/\/www.hostinger.com\/au\/tutorials\/django-forms","default":0},{"locale":"en-NG","link":"https:\/\/www.hostinger.com\/ng\/tutorials\/django-forms","default":0}],"_links":{"self":[{"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/posts\/119338","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/users\/185"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/comments?post=119338"}],"version-history":[{"count":6,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/posts\/119338\/revisions"}],"predecessor-version":[{"id":126621,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/posts\/119338\/revisions\/126621"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/media\/126622"}],"wp:attachment":[{"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/media?parent=119338"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/categories?post=119338"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/tags?post=119338"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}