Martin
Martin

Reputation: 133

Django Formset.is_valid missing 1 required positional argument: 'self'

I was debugging my program and I noticed that on the line Formset.is_valid i am getting error:

missing 1 required positional argument: 'self' 

Could you please advise how it could be solved to make formset and all the forms to validate successfully and save to database. Also, is double validation (formset and form) necessary? Thank you for insights.

views.py

from django.shortcuts import render
from .forms import modelformset_factory, AssumptionsForm
from .models import Assumptions
import pdb

model_names = ['Form1', 'Form2']


def get_assumptions(request):

    if request.method == 'POST':

        print('Reached post')

        formset = modelformset_factory(
            Assumptions, form=AssumptionsForm, extra=5)

        pdb.set_trace()

        for thing in model_names:

            if thing in request.POST:

                print('template name in model_names')

                if formset.is_valid():

                    for form in formset:

                        if form.is_valid():

                        print('in for loop after valid form1')

                        assumptions = form.save(commit='False')
                        assumptions.Name = thing
                        assumptions.save()

    else:

        formset = modelformset_factory(
            Assumptions, form=AssumptionsForm, extra=5)

        print('reached else')

    return render(request, 'assumptions.html', {'formset': formset, 'model_names': model_names})

models.py

from django.db import models
from django.forms import ModelForm

class Assumptions(models.Model):

    Worst_Case = models.FloatField(null=True, blank=True, default=None)
    Grey_Case = models.FloatField(null=True, blank=True, default=None)
    Red_Case = models.FloatField(null=True, blank=True, default=None)
    Blue_Case = models.FloatField(null=True, blank=True, default=None)
    Green_Case = models.FloatField(null=True, blank=True, default=None)
    Best_Case = models.FloatField(null=True, blank=True, default=None)
    Name = models.TextField(null=True, blank=True, default=None)

assumptions.html

<div class="form">
<form action="" method="post">
{% csrf_token %}
{{ formset.management_form }}
{{ formset.non_form_errors.as_ul }}
{% for vardas in model_names %}
<h1>{{vardas}}</h1>
<table id="formset" class="form">
{% for form in formset.forms %}
  {% if forloop.first %}
  <thead><tr>
    {% for field in form.visible_fields %}
    <th>{{ field.label|capfirst }}</th>
    {% endfor %}
  </tr></thead>
  {% endif %}
  <tr class="{% cycle 'row1' 'row2' %}">
  {% for field in form.visible_fields %}
    <td>
    {# Include the hidden fields in the form #}
    {% if forloop.first %}
      {% for hidden in form.hidden_fields %}
      {{ hidden }}
      {% endfor %}
    {% endif %}
      {{ field.errors.as_ul }}
      {{ field }}
    </td>
  {% endfor %}
  </tr>
{% endfor %}
</table>
<input type="hidden" name="{{vardas}}" />
{% endfor %}
<input type="submit" value="Next">

</form>
</div>

forms.py

from django import forms
from django.forms import modelformset_factory, ModelForm
from .models import Assumptions

class AssumptionsForm(ModelForm):

    class Meta:
        model = Assumptions
        fields = ['Worst_Case', 'Grey_Case', 'Red_Case', 'Blue_Case', 'Green_Case', 'Best_Case']
        exclude = ['Name']

Upvotes: 0

Views: 1826

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599788

You haven't instantiated your formset. A factory is something that returns a class, so here modelformset_factory returns a formset class that you then need to instantiate in both your get and post blocks.

def get_assumptions(request):

    AssumptionsFormset = modelformset_factory(
        Assumptions, form=AssumptionsForm, extra=5)

    if request.method == 'POST':
        formset = AssumptionsFormset(request.POST)
        if formset.is_valid():
            ...
    else:
        formset = AssumptionsFormset()
    return render(request, 'assumptions.html', {'formset': formset, 'model_names': model_names})

Also note, you don't need to check is_valid() on each form; if the formset is valid, all the forms will be valid.

Upvotes: 1

Related Questions