How do I retrieve an object instance that was saved previously

I’m trying to slightly modify this django library example (use case#3). In it’s original form the user enters the Book name and Author name(s) on the same page. I’m trying to split the form such that the Book name is created in one form and the Author name is created in the next one. I’m not sure how do I retrieve the just created Book object and attach the Author object to it in the view function.

view.py
    class BookCreateView(CreateView):
    model = Book
    form_class = BookModelForm
    success_url = reverse_lazy('store:create_book_with_authors')

class BookDetailView(DetailView):
    model = Book
    context_object_name = 'book'


def create_book_with_authors(request):
template_name = 'store/create_with_author.html'
if request.method == 'GET':
    bookform = BookModelForm(request.GET or None)
    formset = AuthorFormset(queryset=Author.objects.none())
elif request.method == 'POST':
    bookform = BookModelForm(request.POST)
    formset = AuthorFormset(request.POST)
    if formset.is_valid():

   # here there is no point in saving the bookform since it was already saved by the CreateView, but I'm not sure how to reference to the previously saved Book instance.
   # book = bookform.save() 

    for form in formset:

        author = form.save(commit=False)
        author.book = book
        author.save()
    return redirect(reverse('store:book_detail', kwargs={'pk':book.id}))
`return render(request, template_name, {`
    'formset': formset,
`})`

form.py

from django import forms
from django.forms import modelformset_factory

from .models import Book, Author

class BookModelForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = ('name', )
        labels = {
            'name': 'Book Name'
        }
        widgets = {
            'name': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Enter Book Name here'
                }
            )
        }
AuthorFormset = modelformset_factory(
    Author,
    fields=('name', ),
    extra=1,
    widgets={
        'name': forms.TextInput(
            attrs={
                'class': 'form-control',
                'placeholder': 'Enter Author Name here'
            }
        )
    }
)

Thanks for your help!

You have a couple different ways that this can be done - one of the more popular ones I have seen (and used) involve changing the URL to the second form to require a the primary key from the first page to be part of the request for the second page. Then, in your first page, you get that primary key from the object you just saved and do the reverse_lazy on the URL with the primary key parameter.

You then use that pk part of the url in the second page to create your link to the first model.

Thanks! It worked. I did the following:

  1. Overide the get_success_url in CreateView

    class BookCreateView(CreateView):
        model = Book
        form_class = BookModelForm
    
        def get_success_url(self):
            return reverse('store:create_book_with_authors', kwargs={'pk': self.object.pk})
    
  2. Make create_book_with_authors request primary key of newly created Book.

    `def create_book_with_authors(request, pk):`
         `template_name = 'store/create_with_author.html'
          if request.method == 'GET':
              bookform = BookModelForm(request.GET or None)
              formset = AuthorFormset(queryset=Author.objects.none())
          elif request.method == 'POST':
              bookform = BookModelForm(request.POST)
              formset = AuthorFormset(request.POST)
              if formset.is_valid():`
                  book = Book.objects.get(pk=pk)
                  for form in formset:
                      author = form.save(commit=False)
                     author.book = book
                     author.save()
                 return redirect(reverse('store:book_detail', kwargs={'pk':pk}))
         `return render(request, template_name, {`
             'formset': formset,
         `})`

What should be retured by the create_book_wiht_authors for the DetailView to display newly created Book with Author?

Same idea - if you’re using the generic class-based views, you can override the get_success_url method to create the url with the primary key that points you to your detailed page with that primary key as the parameter.

Ken