mr_bulrathi
mr_bulrathi

Reputation: 554

Trying to use formset, getting __init__() got an unexpected keyword argument 'instance'

I need to use formset, and successfully implemented it for adding objects.

But now i need to use formset for editing objects. I have following:

models.py

class Cell(models.Model):
    content = models.CharField(max_length=100)
    row = models.ForeignKey('Row')

class Row(models.Model):
    pass

forms.py

class RowForm(forms.Form):
    cell = forms.CharField(label="Ячейка", max_length=100)

number_of_cells = 5
RowFormset = formset_factory(RowForm, extra=number_of_cells)

views.py

def edit_row(request, row_pk):
    try:
        row = Row.objects.get(pk=row_pk)
    except Row.DoesNotExist:
        return HttpResponse('Такая строка не существует')

    if request.method == 'POST':
        formset = RowFormset(request.POST, instance=row)
        if formset.is_valid():
            formset.save()
            return HttpResponseRedirect(reverse('table:index'))
    else:
        formset = RowFormset(instance=row)

    return render(request, 'table/edit-row.html', {'formset': formset})

Currently i'm getting TypeError: __init__() got an unexpected keyword argument 'instance'. How can i accomplish my task getting into account that using model form is likely not an option because model doesn't know anything about my cells, or the number of cells i should have in a row (so i presumably must stick to ordinary forms.Form).

Thank you.

Upvotes: 1

Views: 3126

Answers (2)

mr_bulrathi
mr_bulrathi

Reputation: 554

The following code did exactly what i needed:

def edit_row(request, row_pk):
    try:
        row = Row.objects.get(pk=row_pk)
    except Row.DoesNotExist:
        return HttpResponse('Такая строка не существует')

    cells = Cell.objects.filter(row=row)

    contents = []

    if request.method == 'POST':
        formset = RowFormSet(request.POST)
        if formset.is_valid():
            for form in formset:
                cd = form.cleaned_data
                content = cd.get('cell')
                contents.append(content)

            for i, cell in enumerate(cells):
                cell.content = contents[i]
                cell.save()
        return HttpResponseRedirect(reverse('table:index'))
    else:
        formset = RowFormSet()

    return render(request, 'table/edit-row.html', {'formset': formset})

Upvotes: 1

mxle
mxle

Reputation: 481

You get the error because forms.Form isn't supposed to take an instance as an argument. You need to use a formset of Cell model. I suggest this:

forms.py:

from django.forms import modelformset_factory
from .models import Cell

CellFormSet = modelformset_factory(Cell, fields=('content ',))

views.py:

def edit_row(request, row_pk):
    try:
        row = Row.objects.get(pk=row_pk)
    except Row.DoesNotExist:
        return HttpResponse('Такая строка не существует')

    cells = Cell.objects.filter(row=row)

    if request.method == 'POST':
        formset = CellFormSet(request.POST, instance=cells)
        if formset.is_valid():
            formset.save()
            return HttpResponseRedirect(reverse('table:index'))
        else:
            return render(request, 'table/edit-row.html', {'formset': formset})
    else:
        formset = CellFormSet(instance=cells)
        return render(request, 'table/edit-row.html', {'formset': formset})

Upvotes: 3

Related Questions