I have been trying to do Django class-based CreateView and UpdateView with multiple inline formsets
CreateView works fine but UpdateView is not working properly, If anyone tried UpdateView with multiple inline formsets, anyone tried pls share updateview code snippet.
# models.py from django.db import models class Recipe(models.Model): title = models.CharField(max_length=255) description = models.TextField() class Ingredient(models.Model): recipe = models.ForeignKey(Recipe) description = models.CharField(max_length=255) class Instruction(models.Model): recipe = models.ForeignKey(Recipe) number = models.PositiveSmallIntegerField() description = models.TextField() # forms.py from django.forms import ModelForm from django.forms.models import inlineformset_factory from .models import Recipe, Ingredient, Instruction class RecipeForm(ModelForm): class Meta: model = Recipe IngredientFormSet = inlineformset_factory(Recipe, Ingredient, extra=0) InstructionFormSet = inlineformset_factory(Recipe, Instruction, extra=0) # views.py from django.http import HttpResponseRedirect from django.views.generic.edit import CreateView, UpdateView from django.shortcuts import get_object_or_404 from .forms import IngredientFormSet, InstructionFormSet, RecipeForm from .models import Recipe class RecipeCreateView(CreateView): template_name = 'recipe_add.html' model = Recipe form_class = RecipeForm success_url = '/account/dashboard/' def get(self, request, *args, **kwargs): self.object = None form_class = self.get_form_class() form = self.get_form(form_class) ingredient_form = IngredientFormSet() instruction_form = InstructionFormSet() return self.render_to_response( self.get_context_data(form=form, ingredient_form=ingredient_form, instruction_form=instruction_form)) def post(self, request, *args, **kwargs): self.object = None form_class = self.get_form_class() form = self.get_form(form_class) ingredient_form = IngredientFormSet(self.request.POST) instruction_form = InstructionFormSet(self.request.POST) if (form.is_valid() and ingredient_form.is_valid() and instruction_form.is_valid()): return self.form_valid(form, ingredient_form, instruction_form) else: return self.form_invalid(form, ingredient_form, instruction_form) def form_valid(self, form, ingredient_form, instruction_form): self.object = form.save() ingredient_form.instance = self.object ingredient_form.save() instruction_form.instance = self.object instruction_form.save() return HttpResponseRedirect(self.get_success_url()) def form_invalid(self, form, ingredient_form, instruction_form): return self.render_to_response( self.get_context_data(form=form, ingredient_form=ingredient_form, instruction_form=instruction_form)) class RecipeUpdateView(UpdateView): template_name = 'recipe_add.html' model = Recipe form_class = RecipeForm def get_success_url(self): self.success_url = '/account/dashboard/' return self.success_url def get_context_data(self, **kwargs): context = super(RecipeUpdateView, self).get_context_data(**kwargs) if self.request.POST: context['form'] = RecipeForm(self.request.POST, instance=self.object) context['ingredient_form'] = IngredientFormSet(self.request.POST, instance=self.object) context['instruction_form'] = InstructionFormSet(self.request.POST, instance=self.object) else: context['form'] = RecipeForm(instance=self.object) context['ingredient_form'] = IngredientFormSet(instance=self.object) context['instruction_form'] = InstructionFormSet(instance=self.object) return context def post(self, request, *args, **kwargs): self.object = None form_class = self.get_form_class() form = self.get_form(form_class) ingredient_form = IngredientFormSet(self.request.POST) instruction_form = InstructionFormSet(self.request.POST) if (form.is_valid() and ingredient_form.is_valid() and instruction_form.is_valid()): return self.form_valid(form, ingredient_form, instruction_form) else: return self.form_invalid(form, ingredient_form, instruction_form) def form_valid(self, form, ingredient_form, instruction_form): self.object = form.save() ingredient_form.instance = self.object ingredient_form.save() instruction_form.instance = self.object instruction_form.save() return HttpResponseRedirect(self.get_success_url()) def form_invalid(self, form, ingredient_form, instruction_form): return self.render_to_response( self.get_context_data(form=form, ingredient_form=ingredient_form, instruction_form=instruction_form))
Thanks in advance.
I don't think that the regular form of the updateview has to be added to the context because it is there anyways. A working Updateview with inlineformsets could be achieved less complicated. I based this on this Question
class RecipeUpdateView(UpdateView): model = Recipe form_class = RecipeUpdateForm success_url = "/foo/" def get_success_url(self): self.success_url = '/account/dashboard/' return self.success_url def get_object(self): return #your object def get_context_data(self, **kwargs): context = super(RecipeUpdateView, self).get_context_data(**kwargs) if self.request.POST: context['ingredient_form'] = IngredientFormSet(self.request.POST, instance=self.object) context['instruction_form'] = InstructionFormSet(self.request.POST, instance=self.object) else: context['ingredient_form'] = IngredientFormSet(instance=self.object) context['instruction_form'] = InstructionFormSet(instance=self.object) return context def form_valid(self, form): context = self.get_context_data() ingredient_form = context['ingredient_form'] instruction_form = context['instruction_form'] if ingredient_form.is_valid() and instruction_form.is_valid(): self.object = form.save() ingredient_form.instance = self.object ingredient_form.save() instruction_form.instance = self.object instruction_form.save() return self.render_to_response(self.get_context_data(form=form))
My guess is that you can't do
self.object = None
on overwritten post
method in a UpdateView
. So, try
self.object = self.get_object()
instead, once you already have an object instance in this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With