Reputation: 554
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
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
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