Published: Aug. 21, 2019 by lukemakin |  estimated reading time: 7 minutes
In this article we will create a simple form allowing particular user to add/modify/delete skills with rating in scale 1 to 5 in one view. To achieve this result, inline formsets come in handy with a interesting solution. Let's first of all take a look at what we are going to create:

So on our page we have a formset with always one field set empty (containing skill, rate and delete) and we can add as many new skills we want, or simply modify/delete existing ones. In this sample project I defined two models - profiles and skills (which are seperate apps). Now take let's have a quick glance at them starting with Profile model:

from django.db import models
from django.conf import settings

User = settings.AUTH_USER_MODEL

class Profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)

def __str__(self):
return "{}".format(self.user.username)

And skills (with ForeigKey to Profile):

from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
from profiles.models import Profile

class Skill(models.Model):
skill = models.CharField(max_length=100)
rate = models.IntegerField(validators=[
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)

def __str__(self):
return "{}-{}-{}".format(self.profile, self.skill, self.rate)

Now let's take a look at our views. We have a simple home view (template class based view) and a function based view, responsible for the logic behind handling the skill update to a particular user:

from django.shortcuts import render, redirect
from profiles.models import Profile
from skills.models import Skill
from django.forms import modelformset_factory, inlineformset_factory
from django.views.generic import TemplateView, View

class Home(TemplateView):
template_name = 'main/home.html'

def skill_view(request, profile_id):
profile = Profile.objects.get(pk=profile_id)
SkillFormset = inlineformset_factory(
Profile, Skill, fields=('skill', 'rate',), extra=1)

formset = SkillFormset(request.POST or None, instance=profile)
if formset.is_valid():

return redirect('skill',

formset = SkillFormset(instance=profile)

context = {
'formset': formset,
return render(request, 'main/skill.html', context)

So in our skill_view we first needed to define the profile related to the skills and once we've done it, we could move on to create the SkillFormset. To do this we needed to define the type (inlineformset_factory), the fields we wanted to display to the user for creating/updating/deleting and how many empty field sets should there be displayed after submiting. If the request method is post and formset is valid (it won't be valid if you rate i.e. 6 because in the model we defiend rating in scale 1-5) it will be saved to the database and redirected to the current view.

To finish-off let's look at the urls and template:

from django.contrib import admin
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from .views import Home, skill_view

urlpatterns = [
path('', Home.as_view(), name='home'),
path('<profile_id>/', skill_view, name="skill"),

And part of the template containing form:

<form action="." method="POST">
{% csrf_token %}
{{ formset.as_p }}
<button type="submit" class="btn btn-primary btn-sm">Send</button>

This is it! The formset is ready, and the skill update is now easy as never before!

To view additional content login or create a free account
Share your thoughts

No comments yet...

Signup to the newsletter
To get the latest updates from pyplane
© copyright 2019