Search code examples
pythondjangoformsdjango-formsinline-formset

Django: How to create a form using inline_formset with a many to one relationship with user


I am trying to set up a form using Django's inlineformset_factory. The model is set up in a many to one relationship, each user will have many cases. I want the user to add a case.

I have followed the general outline from this site

models.py

class Case(models.Model):
    date_due = models.DateField()
    user = models.ForeignKey(User, on_delete=models.CASCADE)

forms.py

CaseFormset = inlineformset_factory(User,Case, 
                                    fields=('date_due',), 
                                    can_delete = True)

class CaseForm(forms.ModelForm):    
    class Meta:
        model = Case
        fields = ('date_due',)

views.py

@login_required
def add_case(request):
    if request.method == 'POST':
        form = CaseForm(request.POST)
        if form.is_valid():
            case = form.save(commit = False)
            case_formset = CaseFormset(request.POST, instance = case)
            if case_formset.is_valid():
                case.save()
                case_formset.save()
            return redirect('index')
        else:
            print(form.errors)
    else:
        form = CaseForm()
        case_formset = CaseFormset(instance = Case())
    return render(request, 'cases/add_case.html', 
                    {'form':form, 'case_formset':case_formset})

add_case.html

<!DOCTYPE html>
{% load staticfiles %}
<html>

    <head>
        <body>
            <form method="post">
                {% csrf_token %}
                {{ form.as_p }}
                {{ case_formset.as_p }}
                {{ case_formset.management_form }}
                <button type="submit">Save changes</button>
            </form>
        </body>
    </head>
</html>

I am getting a

Exception Type: ValidationError
Exception Value:    
['ManagementForm data is missing or has been tampered with']

Reading the docs it looks like I need to add the management_form to the formset, which I have done. I am not sure where else I am going wrong.

I also tried a different approach from the docs

It looks slightly different than the above and tried to create a formset using the user as an instance. I am not sure which approach is preferable.

I have two questions.

  1. Why I am I getting the above error?
  2. Should I be setting the formset to an instance of user instead of case?

Thanks


Solution

  • I figured it out!

    In views.py I needed to add case.user = request.user

    So views.py looks like

    @login_required
    def add_case(request):
        if request.method == 'POST':
            form = CaseForm(request.POST)
            if form.is_valid():
                case = form.save(commit=False)
                case.user = request.user
                case_formset = CaseFormset(request.POST, instance = case)
                if case_formset.is_valid():
                    case.save()
                    case_formset.save()
                return redirect('index')
            else:
                print(form.errors)
        else:
            form = CaseForm()
            case_formset = CaseFormset(instance = Case())
        return render(request, 'cases/add_case.html', 
                        {'form':form, 'case_formset':case_formset})