0

I think an example will explain it better.

Lets say I am making an application for various Libraries to show what books they have available.

The site will have Users that are registered through the built-in user registration system and User model. These Users (think of it like library members) can visit the Libraries and browse and checkout the available books.

The site will also allow Libraries to register themselves, and part of that registration is declaring a "Librarian," a person who controls what books are available in their particular Library.

I want to create a Library Registration Form that takes the information of this Library and its Librarian and not only creates an instance of the Library model, but also an instance of the User model. The Librarian automatically becomes a User.

This is my current models.py:

    class Library(models.Model):
        name = models.CharField(max_length=200)
        website = models.URLField()
        street = models.CharField(max_length=200)
        city = models.CharField(max_length=200)
        state_or_province = models.CharField(max_length=200)
        postal_code = models.CharField(max_length=200)
        date_registered = models.DateField(auto_now_add=True)
        librarian = models.OneToOneField(User, on_delete=models.CASCADE)

    @receiver(post_save, sender=Library)
    def create_user(sender, instance, created, **kwargs):
        if created:
            User.objects.create(user=instance)
        instance.user.save()

I am currently lost as to how to build views.py and forms.py. I am not even sure that model is built correctly, since I need the form to include not only the Library information, but also User information (first_name, last_name, email, password...). Do I need to duplicate that information in the Library model in order for it to pass to the form?

Basically, I don't have a good grasp of how to models connect to one another via Django tools and files. If anyone can point me in the right direction, I would appreciate it. Thanks!

annmarie-switzer
  • 133
  • 3
  • 14

2 Answers2

0

You can do this with standard django, however it is quite long.

Or you can use django-extra-views, to make your life nice and easy.

class LibrarianInline(GenericInlineFormSet):
    model = User
    fields = '__all__'

class LibraryInline(CreateWithInlinesView):
    model = Library
    inlines = [LibrarianInline]
    fields = '__all__'
Stefan Collier
  • 4,314
  • 2
  • 23
  • 33
0

There is also a simpler way of doing it with standard django. Force the librarian to be created first and only then allow them to create a Library.

urls.py

urlpatterns = [
    url(r'^/create-librarian$', 
        LibrarianCreateView.as_view(), name='create_librarian'),

    url(r'^/create-library/for/(?P<librarian_id>\d+)$',
        LibraryCreateView.as_view(), name='create_library'),
]

views.py

from django.shotcuts import reverse
from django.generic.views import CreateView

class LibrarianCreateView(CreateView):
   model = User

   def form_valid(self, form):
       librarian = form.save(commit=True)
       return redirect('create_library', {'librarian_id': librarian.id})

 class LibraryCreateView(CreateView):
     model = Library

  def form_valid(self, form):
     library = form.save(commit=False)

     librarian_id = self.kwargs['librarian_id']
     # You can do validation here if you fancy
     library.librarian_id = librarian_id
     library.save()

     return self.get_success_url()

By requiring the id of the Librarian to create the Library, it prevents it being created without a librarian.

Stefan Collier
  • 4,314
  • 2
  • 23
  • 33