Reputation: 249
I have the following code. The product is like this: There's a book list. On each book item is a form. This form saves a post and makes it related to this particular book. When you click a book item, you see a list of posts, all related to this book item. So far the book list works fine, saving post data works fine, and when you click a list, it (the DetailView) shows the list of posts (instead of book description, which is usually how DetailView is used) fine. What's not working is saving the post to be related to the particular book on whom is the form that saves the post. More simply, when you save a post, the post should be related to the book that the form is located in.
I'd really appreciate your help. Thanks!
views.py:
class BookList(ListView):
model = Book
template_name='books/books.html'
class PostForm(ModelForm):
class Meta:
model = Post
# Previously I tried, unsuccessfully, this among others:
# books = Book.objects.filter(book)
# posts = Post.objects.filter(the_book=books)
# model = posts
fields = ['post']
widgets = {
'post': forms.Textarea()
}
def get_context_data(self, **kwargs):
context = super(BookList, self).get_context_data(**kwargs)
context['form'] = BookList.PostForm
return context
def post(self, request, *args, **kwargs):
form = BookList.PostForm(request.POST)
if form.is_valid():
form.save()
return render(request, self.template_name, {'form': form })
class Posts(DetailView):
model = Book
template_name='books/post_create.html'
slug_field = 'id'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
book = self.object
posts = Post.objects.filter(the_book=book)
context['posts'] = posts
return context
models.py:
class Book(models.Model):
book = models.CharField(max_length=1000, blank=False, null=False, default="1")
def __str__(self):
return self.book
class Post(models.Model):
post = models.CharField(max_length=1000, blank=False, null=False)
the_book = models.ForeignKey('Book', on_delete=models.CASCADE, default="1")
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.post
books.html:
<ul>
{% for book in object_list %}
<div class='ui card'>
<a class="content" href='{% url 'books:posts' book.id %}'>
<div class="header">{{ book }}</div>
</a>
<div class="ui bottom attached button">
<form class='ui form' action='' method='post'> {% csrf_token %}
{{ form.as_p }}
<div class='postbutton'>
<input class='ui button' type="submit" value="Done" />
</div>
</form>
</div>
</div>
{% empty %}
<h5>You don't have any books!</h5>
{% endfor %}
post_create.html (the name will be changed later...):
<ul>
{% for post in posts %}
<div class='ui card'>
<a class="content">
<div class="header">{{ post }}</div>
</a>
</div>
{% empty %}
<h5>You don't have any posts!</h5>
{% endfor %}
Upvotes: 0
Views: 60
Reputation: 10352
Try this: add a book_id hidden input in your form:
<form class='ui form' action='' method='post'> {% csrf_token %}
{{ form.as_p }}
<input type="hidden" name="book_id" value="{{ book.id }}">
<div class='postbutton'>
<input class='ui button' type="submit" value="Done" />
</div>
and use it in your BookList view:
def post(self, request, *args, **kwargs):
form = BookList.PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.the_book_id = request.POST['book_id']
post.save()
return render(request, self.template_name, {'form': form })
Upvotes: 1