0

I am trying to create a new object Book using HTML form but I get HttpResponse None. I find almost the same case here: Django ModelForm with foreign key but my code still doesn't work. I can't find what is wrong.

models.py

class Author(models.Model):
    """ Author's class - defines an book's author """
    name = models.CharField(max_length=140)

    def __str__(self):
        return self.name

class Book(models.Model):
    """ Book class - defines a book """
    title = models.CharField(max_length=140)
    author = models.ForeignKey("Author", on_delete=models.CASCADE)
    read = models.BooleanField(default=False)

forms.py

class BookForm(forms.ModelForm):
    title = forms.CharField(max_length=200)
    author = forms.ModelChoiceField(queryset=Author.objects.all())
    class Meta:
        model = Book
        fields = ["title", "author", "read"]

class AuthorForm(forms.ModelForm):
    class Meta:
        model = Author
        fields = ["name"]

books.html

<form class="form-inline my-2 my-lg-0" method="POST">
    {% csrf_token %}
    <input class="form-control mr-sm-2" type="text" placeholder="Title" aria-label="addbook" name="title">
    <input class="form-control mr-sm-2" type="text" placeholder="Author" aria-label="addbook" name="author">
    <button class="btn btn-outline-secondary my-2 my-sm-0" type="submit">Add New Book</button>
</form>

views.py

def books(request):
    if request.method == 'POST':
        form = BookForm(request.POST or None)
        if form.is_valid():
            form.save(commit=True)
            all_books = Book.objects.all
            all_authors = Author.objects.all
            return render(request, 'books.html', {'all_books': all_books, 'all_authors':all_authors})
    else:
        all_books = Book.objects.all
        all_authors = Author.objects.all
        return render(request, 'books.html', {'all_books': all_books, 'all_authors':all_authors})

I guess something is wrong with views.py or books.html. I read a big part of Django documentation but still doesn't find an answer that will help me in my case.

Daniel Milewski
  • 109
  • 2
  • 11

1 Answers1

0

You have several issues in your view, but the biggest problem is that you have no code for the case when the form is not valid. You need to have the render call at the same level as the if statement, not within it.

Also, you need to redirect after a success, not render. Finally, you should only set the books and authors once; and all is a method, it needs to be called.

def books(request):
    if request.method == 'POST':
        form = BookForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('somewhere') # could be back to the same URL
    else:
        form = BookForm()        
    all_books = Book.objects.all()
    all_authors = Author.objects.all()
    return render(request, 'books.html', {'all_books': all_books, 'all_authors':all_authors, 'form': form})

(Note, your form is probably not valid because you require the read field but don't include it on your template. You should use the form object itself to render the fields, as well as the errors. Once again, all this is in the documentation.)

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895