# Model Formset in Django

# Django Model Formsets

## Introduction

Formset is a way of working with multiple forms at the same time. Using Formset you can use multiple forms on a single page. In this article, we will be creating formset using a model and see all the options that are available to customize formset.

## Creating Formset

To create a formset we use the `modelformset_factory` function. You pass the Model and fields for which you want to make the `Formset`. `modelformset_factory` returns the Formset for the given model with the provided fields. Therefore it will be something like this:

```python
from django.forms import modelformset_factory,ModelForm
from django.db import models

# Note Model Definition
class Note(models.Model):
    title = models.CharField(max_length=80)
    description = models.TextField()


# Here we create a formset of Note
NoteFormset = formset_factory(Note, fields=['title','description'])
```

While creating a formset you can pass an additional parameter **extra** with a number then the **Formset** will contain that many empty forms.

If you have created a `ModelForm` with custom fields you can pass it to `modelformset_factory`

```python
#Example 
#Creating formset from NoteForm For Note with 5 empty forms
NoteFormset = formset_factory(Note,NoteForm, extra=5)
# This will create 5 empty forms in the formset
```

## Formset with initial data

You can provide initial data for forms by passing a list of dictionaries with data. This will create forms equal to the length of initial data provided(*Total number of dictionaries in the initial data list*) + the value of the `extra` parameter passed during the creation of **Formset**. If you want to fill data from the database you can pass queryset as keyword argument and the forms will be filled with the data from the passed queryset.

Look at this code for better clarity.

```python
NoteFormset = formset_factory(NoteForm,extra=5)
# This formet contains 5 empty forms
# This list contain 3 dictionaries
data = [
        {'title':"note no-1","description":"description-1"},
        {'title':"note no-2","description":"description-2"},
        {'title':"note no-3","description":"description-3"}
        ]
# We passed the initial data to the NoteFormset
# Now forms contain 3 forms with data and 5 empty forms
# So total 8 
# filling the form with initial data
forms = NoteFormset(initial=data)

# Passing data from database
# for filling formset with queryset
forms = NoteFormset(queryset=Note.objects.all())
# for keeping the formset empty
forms = NoteFormset(queryset=Note.objects.none())
```

In this way, you can provide data to be filled in the forms of the `formset`.

## Controlling the number of forms in a Formset

You can also control the number of forms to be displayed. For this, you need to pass another parameter called `max_num` to the `Formset`. Have a look at the following snippet.

```python
# This list contain 3 dictionaries
data = [
        {'title':"note no-1","description":"description-1"},
        {'title':"note no-2","description":"description-2"},
        {'title':"note no-3","description":"description-3"}
        ]

formset = NoteFormset(initial=data, extra=4, max_num=5)
# This form will display 3 forms filled with data and 2 empty forms
# Keep this in mind if the number of forms with data exceeds the max_num
# then also all the forms with the data will be created but 0 empty forms
```

Even if you provide the `max_num` less than forms with data then all forms with data + empty forms till `max_num` will be created.

Another parameter `absolute_max` can be passed to `formset_factory` to set the limit for the number of forms to create from POST data or initial data. In this way even if the initial data exceeds the `absolute_max` still only `absolute_max` number of forms will be instantiated.

```python
NoteFormset = formset_factory(Note, NoteForm, absolute_max=30)
# Now NoteFormset cannot contain forms more than absolute_max value
```

**<mark>Note:</mark>** <mark>Absolute_max should be greater than max_num else ValueError will be raised</mark>

### Passing the POST data to a formset

To pass POST data you simply do this

If your form also deals with files/images don't forget to pass `request.FILES` to the `formset` while processing formset

```python
formset = NoteFormset(request.POST, request.FILES)
if formset.is_valid():
    formset.save()
```

## Formset validation

To validate a `formset` call `is_valid()`. This will validate if the data entered in the forms was valid or not. `is_valid()` method returns a boolean denoting whether `formset` is valid or not.

## Rendering Formset in templates

Now, we will be looking at how to render formset in a template

```python
# View function
def process_form(request):
    if request.method=='POST':
        # processing formset
        return redirect('next view')
    data = Note.objects.all()
    # If we do not provide any argument to the formset then
    # also it will be filled with queryset of the model
    formset = NoteFormset()
    return render(request,'template/form.html',context={'formset',formset})
```

Let's look at <mark>form.html</mark>

**Note**: <mark>If you are dealing with files/images in the form don't miss</mark> `enctype="multipart/form-data"`

```xml
<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ formset.management_form }}
    {% for form in formset %}
        {{ form.as_p }}
    {% endfor %}
    <input type="submit" value="Save">
</form>
```

<mark>It is important to include a management form inside the HTML form. So you will add </mark> `{{formset.management_form}}`

And this is all that you need to know to start using model formsets. For learning more about formset read the official docs here [**Formset**](https://docs.djangoproject.com/en/4.2/topics/forms/formsets/) and [**ModelFormset**](https://docs.djangoproject.com/en/4.2/topics/forms/modelforms/#model-formsets).

### **So are still reading why don't you like this post and share it will your fellow pythonistas and learners?**

### **<mark>Share your views and story of learning tech.</mark>**
