How to restrict Django users from filling a form twice in different sessions

Question:

I have a form for employees to fill their bio data, I want to restrict the employees from viewing the form more than once.

That is after filling the form, you can’t view the empty form anymore, you can only follow an update link to update the form.

I used the Django is_authenticated function for the user registration and login pages, I am looking for a way to do something similar for my current issue.

Asked By: Raji Muhammad

||

Answers:

Sure, here’s an example of how you can restrict employees from viewing the form more than once:

First, you’ll need to add a boolean field to your Employee model to track whether the form has been filled out or not:

from django.db import models
from django.contrib.auth.models import User

class Employee(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    bio_data_filled = models.BooleanField(default=False)

When an employee fills out the form, you’ll need to set the bio_data_filled field to True:

from django.shortcuts import render
from .models import Employee
from .forms import BioDataForm

def bio_data_view(request):
    employee = request.user.employee
    
    if employee.bio_data_filled:
        # If the form has already been filled out, redirect to the update view
        return redirect('update_bio_data')
    
    if request.method == 'POST':
        form = BioDataForm(request.POST)
        if form.is_valid():
            # Save the form data and mark the form as filled out
            employee.bio_data_filled = True
            employee.save()
            form.save()
            return redirect('success')
    else:
        form = BioDataForm()
    
    return render(request, 'bio_data.html', {'form': form})

n this example, we first check if the bio_data_filled field is True for the current employee. If it is, we redirect them to the update view instead of showing the form again. If it’s False, we continue to show the form as normal.

After the employee fills out the form and it’s saved, we mark the bio_data_filled field as True before saving the employee and the form data.

Finally, you’ll need to add a separate view for updating the form data:

from django.shortcuts import render, redirect
from .models import Employee
from .forms import BioDataForm

def update_bio_data_view(request):
    employee = request.user.employee
    
    if not employee.bio_data_filled:
        # If the form has not been filled out yet, redirect to the fill-out view
        return redirect('bio_data')
    
    if request.method == 'POST':
        form = BioDataForm(request.POST, instance=employee.bio_data)
        if form.is_valid():
            form.save()
            return redirect('success')
    else:
        form = BioDataForm(instance=employee.bio_data)
    
    return render(request, 'update_bio_data.html', {'form': form})

In this view, we check if the bio_data_filled field is False for the current employee. If it is, we redirect them to the fill-out view instead of showing the update form. If it’s True, we show the update form as normal.

When the form is submitted and saved, we redirect to the success view just like before.

With these changes, employees will only be able to fill out the form once, and will need to use the update view to modify their existing data.

Answered By: Dharmendra Rathod

Since you’re trying to persist the form submission across sessions, you can persist this information in the database or may also consider storing this info in redis. Here I’m assuming you’ll be using the database.

You may keep track of this information in the existing Employee model, or if you know that you maybe have to extend this to other forms, you can create a separate model.

Here I’m using a separate a model that keep tracks of this information (if a row exists, it indicates that the form is already filled)

class EmployeeFormSubmission(models.Model):
    employee = models.OneToOneField(User, on_delete=models.CASCADE)

If you want to keep track of multiple forms, you can add another fields like form_name.

Finally, you can check if the current_employee already has submitted the form like this, and handle what you really want to do, depending on your business logic (I’ve indicated that in the code comments)

if EmployeeFormSubmission.objects.filter(employee=request.user).exists():
   # You can display an error here, or redirect in the view for 
   # editing the information.
else:
   # This is a new form for the user, so they can fill this in.
   form = EmployeeForm()

 # return the form/error from the view.
Answered By: Sanyam Khurana