1

In Django, I want to create a form that involves 2 Models - a Library model and a Book model. The Library can contain multiple Books.

class Library(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    for_library = models.ForeignKey(Library, null=False, on_delete=models.PROTECT)
    title = models.CharField(max_length=200)
    author = models.CharField(max_length=100)

Now, I have created a Library with id=1 and now want to create a form to tag multiple books to the library. How can I create the form such that the fields look like (including pre-filling the library ID):

Library: <id=1 Library>

Book1 Title:  _____
Book1 Author: _____
Book2 Title:  _____
Book2 Author: _____

The furthest I have gone is:

BookFormset = inlineformset_factory(Library, Book,
    fields=['title', 'author'], form=CreateBookForm, extra=2, min_num=1, max_num=20, 
    can_delete=True)

But cannot continue and am not sure of integrating this with views.py. Any help on this?

bryan.blackbee
  • 1,934
  • 4
  • 32
  • 46

1 Answers1

1

Basically, you should have something like this in your views.py:

def library_books(request, library_pk):
    if request.method == 'POST':
        library = Library.objects.get(pk=pk)
        formset = forms.BookFormset(request.POST, instance=library)
        if formset.is_valid():
            formset.save()
        # ...

and in forms.py:

from .models import Library, Book

BookFormset = inlineformset_factory(Library, Book,
    fields=['title', 'author'], extra=2, min_num=1, max_num=20, 
    can_delete=True)

keep in mind that as you don't need to specify a custom form in inlineformset_factory as long as you are satisfied with the default form.

template:

<form method="post"> {% csrf_token %}
    {{ formset }}
</form>

Check the docs if you want to have more control on how the forms are displayed in the template.

Pedram Parsian
  • 3,750
  • 3
  • 19
  • 34
  • sorry id like to do this in a CBV setting, sorry forgot to add that as a requirement – bryan.blackbee Dec 06 '19 at 08:52
  • @bryanblackbee If you want to use CBV, you should use `CreateView` and override `get` and `post` methods. Check out [this](https://stackoverflow.com/questions/16951751/saving-inlineformset-in-django-class-based-views-cbv) and let me know if you cant make that work (btw, I prefer working with FBV, because they are more clear in this use-case). – Pedram Parsian Dec 06 '19 at 09:16