Model Formsets in Django

ModelFormsets are a more advanced approach of dealing with numerous forms built using a model and using them to construct model instances in Django. In other words, ModelFormsets are a collection of Django forms. For example, you might want to create many forms on a single page, each of which may require multiple POST requests.

class CodeModel(models.Model):
  title = models.CharField(max_length = 200)
  description = models.TextField()

Now, if you want to make a modelformset for this model, you’ll need to use modelformset_factory. A formset refers to a layer of abstraction that allows you to handle several forms on a singular page. It’s easiest to relate the latter to a data grid.

Following that, we’ll go over the characteristics of model formsets, expanding on the prior knowledge of standard formsets. So, suppose you’re unfamiliar with formset words (such as factory and management form). In that case, you can read the article “formsets in Django” because the rest of this section assumes you already know these fundamental formset ideas.

from django.forms import formset_factory
CodeFormSet = modelformset_factory(CodeModel)

Django Model formset factory

Working with model formsets relies heavily on the modelformset_factory() method. The modelformset_factory() method can take up to nineteen arguments, nine of which are the same as standard formsets, and the rest are unique to model formsets.

The names and default values for each argument in the modelformset_factory() method are shown in the following snippet, with bolded text reflecting model formset specific choices.

modelformset_factory(model, queryset=model.objects.all(),
              form=ModelForm,fields=None, exclude=None,
              formset=BaseModelFormSet, extra=1, can_order=False, can_delete=False,
              max_num=None, min_num=None, validate_max=False, validate_min=False,
              widgets=None, localized_fields=None,labels=None,
              help_texts=None, error_messages=None,
              field_classes=None,formfield_callback=None)

The only argument for the modelformset_factory() method (that is, one that does not have a default value) is the model, as you can see in this example. Each argument has the following meaning:

  • model.- Defines the model class from which a formset will be created.
  • queryset- Defines the queryset that will be used to construct the formset. By default, all model records (including the model.objects.all() queryset if applicable) generate the formset.
  • fields – Like the fields meta-model form option, this option specifies which model form fields should be included in the model when creating the model formset.
  • exclude – Like the exclude meta-model form option, this option specifies which model form fields to omit as part of the model when creating the model formset.
  • widgets – Like the widgets meta-model form option, this option defines overriding widgets for the model form to generate the model formset.
  • localize fields.- Just like the localize_fields meta-model form option, this specifies which model form fields to localize (i.e., support several languages) while creating the formset.
  • labels.- Defines the model form’s overriding label for creating the model.
  • Formset- formset is similar to the meta-model form option labels.
  • help text.- Overrides the model form’s help text to build the model formset, similar to the help_texts meta-model form option.
  • error_messages- Like the help_texts meta-model form option, this defines overriding error messages for the model form when creating the model formset.
  • field_classes -Like the field_classes meta-model form option, this defines overriding field classes for the model form to generate the model formset.
  • formsetfield_callback.- Defines a method executed before a form field is created from a model field. In the context of a formset, this is typically used to alter a model form field (as mentioned in the earlier model form section).

Django ModelFormsets

To illustrate rendering Django ModelFormsets manually using an example, consider a project called Codeunderscored, with a code app.

Make a new file named models.py in your code app, where you will be creating all of your models. Django Models is required to create a Django model. Let’s look at an example in your models.py file.

# importing Django's standard Model from the built-in library
from django.db import models

# declaration of a new model with a name "CodeModel"
class CodeModel(models.Model):

	# fields of the model
	title = models.CharField(max_length = 200)
	description = models.TextField()

	# renames the instances of the model
	# with their title name
	def __str__(self):
		return self.title

Let us explain what’s going on. You describe the field’s name on the left side, and on the right, you define the input field’s numerous functionalities. The following syntax denotes the syntax of a field:

Field_name = models.FieldType(attributes)

The next step is to access the views.py and create a formset_view as shown below to make a simple formset of this form.

from django.shortcuts import render

# importing forms  relatively
from .forms import CodeForm

# importing formset_factory
from django.forms import formset_factory

def formset_view(request):
	context ={}

	# creating a formset
	CodeFormSet = modelformset_factory(CodeForm)
	new_formset = CodeFormSet()
	
	# Addition of  the formset to the dictionary's context
	context['formset']= new_formset
	return render(request, "home.html", context)

Create a “home.html” html file to render the formset in HTML. Now go to templates > home.html and make some changes as follows:

<form method="POST" enctype="multipart/form-data">
	{%% csrf_token %%}
	{{ formset.as_p }}
	<input type="submit" value="Submit">
</form>

Then, go to http://localhost:8000/ to see if your formset is working or not. Your modelformset should be fully functional. If so, let’s look at how to change this formset so that you can take advantage of its additional capabilities.

How to use Django ModelFormsets in creating many forms

Multiple instances of a form are handled using Django formsets. Using Django Formsets’ additional feature, it is simple to generate numerous forms. In the code/views.py file,

from django.shortcuts import render

# relative import of forms
from .models import CodeModel

# importing formset_factory
from django.forms import modelformset_factory

def modelformset_view(request):
	context ={}

	# creating a formset and three instances of CodeForm
	CodeFormSet = modelformset_factory(CodeModel, fields =['title', 'description'], extra = 3)
	new_formset = CodeFormSet()

			
	# Addition of the dinctionary's context to the formset
	context['formset']= new_formset
	return render(request, "home.html", context)

It will construct a formset that can deal with the data linked with the CodeModel model. We can also feed the queryset data to the model formset to only update the queryset we’ve given it.

formset = CodeFormSet(queryset=CodeModel .objects.filter(title__startswith='M'))

The keyword argument extra duplicates the same form numerous times. Enter extra = 3 to produce three forms, and similarly for the others. To see if three forms have been created, go to http://localhost:8000/.

Using Django Formsets to handle many forms

It’s much easier to create a form than it is to manage the data entered into those fields on the back end. Let’s look at how to use the data from a model formset in a view with ease. Django formsets required one extra argument, {{ formset.management_data}} when attempting to handle them. Understanding the ManagementForm is an excellent place to start if you want to learn more about managing data. templates/home.html contains the following code.

<form method="POST" enctype="multipart/form-data">
	
	<!-- Management data of formset -->
	{{ formset.management_data }}

	<!-- Security token -->
	{%% csrf_token %%}

	<!-- Using the formset -->
	{{ formset.as_p }}
	
	<input type="submit" value="Submit">
</form>

Now, change formset_view to print the data to see how and what type of data is shown. code/view.py is a Python script that displays information about codeunderscored.

from django.shortcuts import render

# import of forms relatively
from .forms import GeeksForm

# importing formset_factory
from django.forms import formset_factory

def formset_view(request):
	context ={}

	# creating a formset and three instances of CodeForm

	CodeFormSet = formset_factory(CodeForm, extra = 3)
	new_formset = CodeFormSet(request.POST or None)
	
	# printing of the data in the formset if it is valid
	if new_formset.is_valid():
		for form in new_formset:
			print(form.cleaned_data)
			
	# Addion of the  dictionary's  context to
	context['formset']= new_formset
	return render(request, "home.html", context)

Try filling out the formset using http://localhost:8000/. When you submit the form, the information is saved in CodeModel, when the server is running. This information is used in any convenient way.

In general, Django’s model formsets validate when at least one field is filled. However, in most cases, we’ll need a scenario where at least one object data is added or another scenario where we’ll need to pass some initial data to the form. We can achieve this by overriding basemodelformset.

Conclusion

Django model forms can be joined together as a set in a model formset, just like regular Django forms can. Model formsets are similar to standard formsets in the same way that Django model forms are similar to standard Django forms.

Django includes a model formset, similar to standard formsets, making working with Django models simple. Model formsets in Django allow you to edit or create many model instances from one form. A factory technique is used to construct Model Formsets. modelformset_factory() is the default factory method. The latter encapsulates the formset factory to the model forms. Inlineformset_factory() can also be used to alter related objects. To confine the queryset and set the starting date to the instance’s related objects, inlineformset_factory encapsulates modelformset_factory.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *