models.py
class Project(models.Model):
description = models.CharField(max_length = 50, blank = True, null = True)
status = models.IntegerField(choices = STATUS_CHOICES,
default = 4)
owner = models.ForeignKey(staff, on_delete = models.CASCADE, blank = True, null = True)
...
class Update(models.Model):
project = models.ForeignKey(Project, on_delete = models.CASCADE)
notes = models.CharField(max_length = 50, blank = True, null = True)
update_date = models.DateTimeField(
default = timezone.now, editable = False)
added_by = models.CharField(max_length = 35, blank = True)
forms.py
class CreateUpdateForm(ModelForm):
class Meta:
model = Update
fields = ('notes')
class EditProjectForm(ModelForm)
class Meta:
model = Project
fields = ('__all__')
views.py
def mds_projects(request):
project_formset = modelformset_factory(Project, form = EditProjectForm, extra = 0)
if request.method == 'POST':
formset = project_formset(request.POST, request.FILES)
if formset.is_valid():
for f in formset:
project = f.save(commit = False)
update_form = CreateUpdateForm(request.POST, request.FILES)
if update_form.is_valid():
update = update_form.save(commit = False)
update.project = project
project.save()
update.save()
else:
print(update_form.errors)
return redirect('MDS_Projects')
else:
print(formset.errors)
else:
projects = Project.objects.filter(dept = 'Assistive Technology')
formset = project_formset(queryset = projects)
update_form = updateForm()
return render(request, 'MDSprojectsB.html', {
'formset': formset,
'update_form': update_form
})
ModelForm is a regular Form which can automatically generate certain fields. The fields that are automatically generated depend on the content of the Meta class and on which fields have already been defined declaratively. Basically, ModelForm will only generate fields that are missing from the form, or in other words, fields that weren’t defined declaratively.,Fields defined declaratively are left as-is, therefore any customizations made to Meta attributes such as widgets, labels, help_texts, or error_messages are ignored; these only apply to fields that are generated automatically.,The generated Form class will have a form field for every model field specified, in the order specified in the fields attribute.,You can only use this technique to opt out from a field defined declaratively by a parent class; it won’t prevent the ModelForm metaclass from generating a default field. To opt-out from default fields, see Selecting the fields to use.
>>> from django.forms
import ModelForm
>>>
from myapp.models
import Article
# Create the form class. >>>
class ArticleForm(ModelForm):
...class Meta:
...model = Article
...fields = ['pub_date', 'headline', 'content', 'reporter']
# Creating a form to add an article. >>>
form = ArticleForm()
# Creating a form to change an existing article. >>>
article = Article.objects.get(pk = 1) >>>
form = ArticleForm(instance = article)
from django.db
import models
from django.forms
import ModelForm
TITLE_CHOICES = [
('MR', 'Mr.'),
('MRS', 'Mrs.'),
('MS', 'Ms.'),
]
class Author(models.Model):
name = models.CharField(max_length = 100)
title = models.CharField(max_length = 3, choices = TITLE_CHOICES)
birth_date = models.DateField(blank = True, null = True)
def __str__(self):
return self.name
class Book(models.Model):
name = models.CharField(max_length = 100)
authors = models.ManyToManyField(Author)
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ['name', 'title', 'birth_date']
class BookForm(ModelForm):
class Meta:
model = Book
fields = ['name', 'authors']
from django
import forms
class AuthorForm(forms.Form):
name = forms.CharField(max_length = 100)
title = forms.CharField(
max_length = 3,
widget = forms.Select(choices = TITLE_CHOICES),
)
birth_date = forms.DateField(required = False)
class BookForm(forms.Form):
name = forms.CharField(max_length = 100)
authors = forms.ModelMultipleChoiceField(queryset = Author.objects.all())
from django.core.exceptions
import NON_FIELD_ERRORS
from django.forms
import ModelForm
class ArticleForm(ModelForm):
class Meta:
error_messages = {
NON_FIELD_ERRORS: {
'unique_together': "%(model_name)s's %(field_labels)s are not unique.",
}
}
>>> from myapp.models import Article >>> from myapp.forms import ArticleForm # Create a form instance from POST data. >>> f = ArticleForm(request.POST) # Save a new Article object from the form 's data. >>> new_article = f.save() # Create a form to edit an existing Article, but use # POST data to populate the form. >>> a = Article.objects.get(pk = 1) >>> f = ArticleForm(request.POST, instance = a) >>> f.save()
# Create a form instance with POST data. >>> f = AuthorForm(request.POST) # Create, but don 't save the new author instance. >>> new_author = f.save(commit = False) # Modify the author in some way. >>> new_author.some_field = 'some_value' # Save the new instance. >>> new_author.save() # Now, save the many - to - many data for the form. >>> f.save_m2m()
Last Updated : 09 Jan, 2020
class GeeksModel(models.Model):
title = models.CharField(max_length = 200)
description = models.TextField()
Now if one wants to create a modelformset for this model, modelformset_factory needs to be used. A formset is a layer of abstraction to work with multiple forms on the same page. It can be best compared to a data grid.
from django.forms
import formset_factory
GeeksFormSet = modelformset_factory(GeeksModel)
Let’s explain what exactly is happening, left side denotes the name of the field and to right of it, you define various functionalities of an input field correspondingly. A field’s syntax is denoted as
Syntax :
Field_name = models.FieldType(attributes)
Let’s explain what exactly is happening, left side denotes the name of the field and to right of it, you define various functionalities of an input field correspondingly. A field’s syntax is denoted as
Syntax :
Field_name = models.FieldType(attributes)
modelformset_factory() requires the first argument be the model the formset is for. After specifying the model, different optional arguments can be specified. We'll use two optional arguments - fields and extra.,Once we have created the formset instance, we call render_to_response with the argument being a dictionary that has the formset assigned to the bird_formset key.,Formsets can be created for different types of forms, including model forms. Since we want to create new instances of the Bird model, a model formset is a natural fit.,The model form requires we specify the model we want the form to be associated with and the fields we want to include in the form.
The app will only have one model, Bird
, that stores information about each bird we've seen.
# models.py
from django.db
import models
class Bird(models.Model):
common_name = models.CharField(max_length = 250)
scientific_name = models.CharField(max_length = 250)
def __str__(self):
return self.common_name
We will manage URLs with a project level urls.py
file set to include the app level urls.py
file.
# project level urls.py from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('birds.urls')), ]
The app level urls.py
will include the paths to the two pages of the app.
# app level urls.py from django.urls import path from.views import BirdAddView, BirdListView urlpatterns = [ path('add', BirdAddView.as_view(), name = "add_bird"), path('', BirdListView.as_view(), name = "bird_list") ]
If we just wanted to add a single model form to our page, we would create it like this:
# forms.py
from django.forms
import ModelForm
from.models
import Bird
# A regular form, not a formset
class BirdForm(ModelForm):
class Meta:
model = Bird
fields = [common_name, scientific_name]
To create a model formset, we don't need to define the model form at all. Instead, we use Django's modelformset_factory()
which returns a formset class for a given model.
# forms.py from django.forms import modelformset_factory from.models import Bird BirdFormSet = modelformset_factory( Bird, fields = ("common_name", "scientific_name"), extra = 1 )
In order to use ModelFormSet, Django makes use of modelformset_factory.,In Django, ModelFormsets is an advanced way to handle multiple forms created with a model. ModelFormSets uses the model to create model instances.,Just as standard Django forms can be grouped together as a set in a Django FormSet, Django model forms can be grouped into a ModelFormSet. ModelFormSet also has a lot of similarities with the standard FormSet.,The example below demonstrates how ModelFormSet can be used.
Installation
pip install pipenv pipenv shell pipenv install django
Then:
django - admin startproject DjangoFormset. /
django-admin startproject DjangoFormset ./
python manage.py startapp codebase python manage.py migrate python manage.py runserver
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'codebase'
]
from django.db
import models
# adding the model
class ModelFormSetModel(models.Model):
name = models.CharField(max_length = 200)
email = models.CharField(max_length = 200)
department = models.TextField()
# the name of the model that will be showing in the admin panel
class Meta:
verbose_name_plural = 'data'
#so it will use emaill to reference a particular data
def __str__(self):
return self.email
For example:
from.models
import ModelFormsetModel
from django.forms
import modelformset_factory
DjangoFormset = modelformset_factory(ModelFormsetModel, fields = '__all__')
from django.shortcuts import render #importing the model from.models import ModelFormSetModel # importing django modelformset_factory used for modelformset from django.forms import modelformset_factory def home(request): #displaying the neccessary fields needed to be displayed on the frontend DjangoFormSet = modelformset_factory(ModelFormSetModel, fields = ['name', 'email', 'department']) # refrencing the DjangoFormset as a method formset = DjangoFormSet() # Add the formset to context dictionary context = { 'formset': formset } return render(request, "app/home.html", context)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Django ModelFormSets</title>
</head>
<body>
<form method="POST" enctype="multipart/form-data">
<!-- csrf token -->
{% csrf_token %}
<!-- displaying the form from the backend -->
{{ formset.as_p }}
<input type="submit" value="Submit">
</form>
</body>
</html>