why django inlineformset_factory data not saving in class-based updateview?

inlineformset_factory fields is rendering in my html template. Others fields data saving except inlineformset_factory fields. here is my code:

models.py

class HeaderImage(models.Model):
      header_image = models.ImageField()
      post = models.ForeignKey(Post, on_delete=models.CASCADE)

froms.py

BlogImageFormSet = inlineformset_factory(Post,  # parent form
                                                  HeaderImage,  # inline-form

                                                fields=['header_image'] ,can_delete=False, extra=1)

#views.py

class BlogUpdateView(PermissionRequiredMixin,UpdateView):
      raise_exception = True
      permission_required = "blog.change_post"
      model = Post
      template_name = "blog_update_post.html"
      form_class = BlogPost

      def get_success_url(self):
        self.success_url = 'http://127.0.0.1:8000/blog'
        return self.success_url
                   
      def get_context_data(self, **kwargs):
        context = super(BlogUpdateView, self).get_context_data(**kwargs)
        if self.request.POST:
            context['form'] = BlogPost(self.request.POST, instance=self.object)
            context['ingredient_form'] = BlogImageFormSet(self.request.POST, instance=self.object)
            
        else:
            context['form'] = BlogPost(instance=self.object)
            context['ingredient_form'] =BlogImageFormSet(instance=self.object)
        return context
      

      def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        ingredient_form = BlogImageFormSet(self.request.POST)
        if (form.is_valid() and ingredient_form.is_valid()):
            return self.form_valid(form, ingredient_form)
        else:
            return self.form_invalid(form, ingredient_form)


      def form_valid(self, form, ingredient_form):
        self.object = form.save()
        ingredient_form.instance = self.object
        ingredient_form.save()
        return HttpResponseRedirect(self.get_success_url())
      

      def form_invalid(self, form, ingredient_form):
        return self.render_to_response(
            self.get_context_data(form=form,
                                  ingredient_form=ingredient_form,
                                 ))

I am not understanding why data is not saving for inlineformset_factory field. see the picture for better understand enter image description here

What information are you looking at to determine that the data is not being saved from that form?

I am not understand why my code is not working.

How do you know that the code is not working? What are you looking at that is making you believe that the data is not being stored?

I am checking it to my backend… others fields data updating except inlineformset_factory fields

Ok, notice the difference between how you’re rebuilding the BlogImageFormSet object in your post method and how the formset is being rebuilt in the docs at Creating forms from models | Django documentation | Django

I am using class-based view not function based view. Your example for FBV

Doesn’t matter - I’m focusing on that one line:
ingredient_form = BlogImageFormSet(self.request.POST)

which line??? can you explain

I assume you need to call get_context_data on your post method.

Why? Because in context_data you’re filling your forms with data from POST.

def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form_class = self.get_form_class()
        form = self.get_form(form_class)

        context = self.get_context_data() # Get context data
        form = context["form"] # Extract form with POSTed data
        ingredient_form = context["ingredient_form"] # Extract formset with POSTed data

        if (form.is_valid() and ingredient_form.is_valid()):
            return self.form_valid(form, ingredient_form)
        else:
            return self.form_invalid(form, ingredient_form)
1 Like

Thnaks marcorichetta. how to call context data in post method? can you please show me an example?

I’ve put an example in my previous reply but, it is important to understand what your code is doing, otherwise, you’ll be in the same situation in the future.

Can you tell why this line is part of the problem? What are you passing to your BlogImageFormSet?

1 Like

Thanks all. my prblem was solved. I was missing self.request.FILES as tried to upload files. Here is my code. Hope it will help others

def get_context_data(self, **kwargs):

        # we need to overwrite get_context_data

        # to make sure that our formset is rendered.

        # the difference with CreateView is that

        # on this view we pass instance argument

        # to the formset because we already have

        # the instance created

        data = super().get_context_data(**kwargs)

        if self.request.POST:

            data["children"] = BlogImageFormSet(self.request.POST, self.request.FILES,instance=self.object)

        else:

            data["children"] = BlogImageFormSet(instance=self.object)

        return data

      def form_valid(self, form):

        context = self.get_context_data()

        children = context["children"]

        self.object = form.save()

        if children.is_valid():

            children.instance = self.object

            children.save()

        return super().form_valid(form)

      def get_success_url(self):

        return reverse("blog")
1 Like