Django automatically set foreign key in form (with class based views)

前端 未结 2 816
孤城傲影
孤城傲影 2021-01-01 03:34

I want to use a form to generate a new object (say a Book) from a Person\'s page such that the new Book is automatically associated with that Person via a foreign key, but I

相关标签:
2条回答
  • 2021-01-01 04:19

    Since the ID is sent with the request, your form does not need a person field. Instead, you need to add the person before the Book is saved.

    Your form should be:

    class BookForm(forms.ModelForm):
        class Meta:
            model = Book
            fields = ('title',)
    

    Your views should be something like this:

    from django.shortcuts import get_object_or_404
    from django.shortcuts import render, redirect
    
    def create_book(request, person_id):
    
         # If the person_id is not valid, don't go forward.
         # return a 404 instead.
    
         person = get_object_or_404(Person, pk=person_id)
    
         book_form = BookForm(request.POST or None)
         if book_form.is_valid():
             new_book = book_form.save(commit=False) # Don't save it yet
             new_book.person = person # Add person
             new_book.save() # Now save it
             return redirect('/')
    
         return render(request, 'book_form.html', {'form': book_form})
    

    In your urls.py, make sure you are passing the id to this view:

    url(r'book/add/(?P<person_id>\d+)/$', create_book, name='create_book')
    

    You would call it like this http://localhost:8000/book/add/1/ (if you are adding for person id 1).

    You also don't need to give your own primary key, django will add one by default to all models, so your Person model should be simply:

    class Person(models.Model):
        name = models.CharField(max_length=200) # Or some other field
    

    Now, your person model will have an automatic pk property, which will be the primary key (whatever it is actually called in your database).

    0 讨论(0)
  • 2021-01-01 04:29

    You're going at it the wrong way: the person is not user input, so this information should not reside in the form. You can override the form_valid method as follows:

    class AddBook(CreateView):
        model = Book
    
        def form_valid(self, form):
            form.instance.person_id = self.kwargs.get('pk')
            return super(AddBook, self).form_valid(form)
    

    This will set the person_id attribute on the instance used by the form to save the data, and then call the super method to save that instance and return a redirect.

    0 讨论(0)
提交回复
热议问题