5

I have a strange problem. I am trying to validate one form sent through POST request, and this form is in fact built on the foundation of four models.

The idea is to validate all the forms and then save them accordingly, in appropriate order, assigning foreign keys on the basis of recently saved model instances.

The problem occurs when I try to assign a value to the foreign key of the model that was properly validated through the form.is_valid() call. It throws however an IntegrityError saying that this specific foreign key "may not be NULL".

Below please find the code that should give you the idea on what I am doing:

Models & forms defitinions:

class Author(models.Model):
    name = models.CharField(blank=False, max_length=150)
    book = models.OneToOneField('Book')  # its important, one author has one book

class Book(models.Model):
    name = models.CharField(blank=False, max_length=150)

class AuthorForm(ModelForm):
    class Meta:
        model = Author
        exclude = ('book',)

class BookForm(ModelForm):
    class Meta:
        model = Book

In one of the views:

if request.method == "POST":
    author_form = AuthorForm(request.POST, prefix='author')
    book_form = BookForm(request.POST, prefix='book')
    if author_form.is_valid() and book_form.is_valid():
        book = book_form.save()
        author_form.cleaned_data['book_id'] = book.id
        author.form.save()  # Error!

During author_form.save() I get error similar to this:

IntegrityError at /api/my_method
myapp_author.book_id may not be NULL

I am completely sure that book.id is an integer (int, I have checked it) with the ID of recently saved Book record.

Do you have any idea how could I set the foreign key having validated & unsaved form, so I can safely save it into the database?

2 Answers 2

6

You've excluded book from the AuthorForm, so Django doesn't care what the value of cleaned_data['book_id'] is - it'll just ignore it.

Instead, you need to set the book property directly on the unsaved author instance:

    book = book_form.save()
    author = author.form.save(commit=False)
    author.book = book
    author.save()
Sign up to request clarification or add additional context in comments.

Comments

3

You could try:

if author_form.is_valid() and book_form.is_valid():
    book = book_form.save()
    author = author_form.save(commit=False)
    author.book = book
    author.save()

Comments

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.