1

I currently have an error with writing UpdateView for double nested forms. My architecture is comprised of one template containing one form and two formsets. There's a large form for publisher. Someone can then add as many author formsets as they want and as many book formsets to each author as they want. So it looks like:

  • Publisher -> Author1, Author2, Author3, ...
  • Author1 -> Book1, Book2, Book3
  • Author2 -> Book4
  • Author3 -> Book5, Book6

Again, this is all listed in one create.html template. I wrote this using CreateView and it works fine. Now with writing UpdateView, I redirect to my html template for the creation of the forms and can correctly populate the form with data for publisher and author. However, when I try to populate the form with the book data, it populates every author instance with the same book instances rather than populate each author instance with their matching book instances. So it looks like:

  • Publisher -> Author1, Author2, Author3, ...
  • Author1 -> Book1, Book2, Book3
  • Author2 -> Book1, Book2, Book3
  • Author3 -> Book1, Book2, Book3

My models.py looks like :

class Publisher(models.Model):
    name = models.CharField(max_length=255, unique=True)

class Author(models.Model):
    name = models.CharField(max_length=255, unique=True) 
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

class Book(models.Model):
    title = models.CharField(max_length=255, unique=True)
    author = models.ForeignKey(Author, on_delete=models.CASCADE) 

My forms.py looks like:

AuthorInlineFormSet = inlineformset_factory(
    Publisher,
    Author,
    fields="__all__",
    extra=1, 
    can_delete=False,
)

BookInlineFormSet = inlineformset_factory(
    Author,
    Book,
    fields="__all__",
    extra=1,
    can_delete=False,
)

My views.py looks like:

class FormCreateView(CreateView):
    model = Publisher
    template_name = 'reservations/create.html'
    fields = "__all__"

    def form_valid(self, form):
        result = super(FormCreateView, self).form_valid(form)

        authors_count = 0
        authors_formset = AuthorInlineFormSet(form.data, instance=self.object, prefix='authors_formset')
        if authors_formset.is_valid():
            authors = authors_formset.save()

            for author in authors:
                books_formset = BookInlineFormSet(form.data, instance=author, prefix='books_formset_%s' % authors_count)
                if books_formset.is_valid():
                    books_formset.save()
                authors_count += 1
        return result

    def get_context_data(self, **kwargs):
        context = super(FormCreateView, self).get_context_data(**kwargs)
        context['authors_formset'] = AuthorInlineFormSet(prefix='authors_formset')
        context['books_formset'] = BookInlineFormSet(prefix='books_formset_0')
        return context

class FormUpdateView(UpdateView):
    model = Publisher 
    template_name = 'reservations/create.html'
    fields = "__all__"

    def get_success_url(self):
        return reverse_lazy('reservations:dashboard')

    def get_object(self, *kargs, **kwargs):
        request = get_object_or_404(Publisher, pk=self.kwargs['pk'])

        return request

    def get_context_data(self, **kwargs):
        context = super(FormUpdateView, self).get_context_data(**kwargs)
        context['authors_formset'] = AuthorInlineFormSet(instance=self.object, prefix='authors_formset')
        authors_count = 0
        authors_formset = AuthorInlineFormSet(instance=self.object, prefix='authors_formset')
        authors_formset = authors_formset.queryset
        for author in authors_formset:
            context['books_formset'] = BookInlineFormSet(instance=author, prefix='books_formset_%s' % authors_count)
        return context 

Now if I were to print out the context['books_formset'] in the for loop of UpdateView's get_context_data, it correctly prints out the matching book formsets for each author, so it'll print out (Book5, Book6), (Book4), and then (Book1, Book2, Book3). So I know it's correctly finding the corresponding book instances for each author instance. However, it then writes all book instances to Book1, Book2, Book3 so each author has Book1, Book2, Book3. I'm not quite sure how to fix this, and would appreciate any help! Thank you so much.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.