Reputation: 69
I have 2 views, DetailView is displaying the post data and CreateView is creating comment to this post. The problem is my template isnt rendering any comment form and theres no error in my console and I have no idea why this is not working. Am i doing something wrong? If yes, Can I implement this differently? If yes, what should I use? Thank you in advance :)
views code:
class PostDetailView(LoginRequiredMixin, DetailView):
model = Post
context_object_name = 'post'
template_name = 'post/details.html'
class CommentCreate(LoginRequiredMixin, CreateView):
model = Comment
form_class = CommentCreationForm
context_object_name = 'forma'
template_name = 'post/details.html'
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
details.html template code:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<h1>POST</h1>
{{ post.content }}
<hr>
<form action="" method="post">
{% csrf_token %}
{{ form }}
<button class="btn btn-default" type="submit">Comment</button>
</form>
{% endblock content %}
comment form:
class CommentCreationForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('text', )
comment model:
class Comment(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
text = models.TextField()
date_posted = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.id)
Upvotes: 1
Views: 68
Reputation: 96
I usually do it by functions instead class
this is my sample code:
views.py: (after all post views)
@login_required
def add_comment_to_post(request ,pk):
post = get_object_or_404(Post,pk=pk)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_detail',pk=post.pk)
else:
form = CommentForm()
return render(request,'blog/comment_form.html',{'form':form})
@login_required
def comment_approve(request,pk):
comment = get_object_or_404(Comment,pk=pk)
comment.approve()
return redirect('post_detail',pk=comment.post.pk)
@login_required
def comment_remove(request,pk):
comment = get_object_or_404(Comment,pk = pk)
post_pk = comment.post.pk
comment.delete()
return redirect('post_detail',pk=post_pk)
models.py:
class Post(models.Model):
author = models.ForeignKey('auth.User',on_delete=models.CASCADE)
title = models.CharField(max_length = 50)
text = models.CharField(max_length=500)
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_time = timezone.now()
self.save()
def approve_comments(self):
return self.comments.filter(approved_comment=True)
def get_absolute_url(self):
return reverse("post_detail",kwargs={'pk':self.pk})
def __str__(self):
return self.title
class Comment(models.Model):
post=
models.ForeignKey('blog.Post',related_name='comments',on_delete=models.CASCAD)
author = models.CharField(max_length=16)
text = models.CharField(max_length=220)
created_date = models.DateTimeField(default=timezone.now)
approved_comment = models.BooleanField(default=False)
def approve(self):
self.approved_comment = True
self.save()
def get_absolute_url(self):
return reverse('post_list')
def __str__(self):
return self.text
Upvotes: 0
Reputation: 477641
If you make a request, you always will end up triggering one view. That view can render, zero, one or more templates to generate a HTTP response, but it does not need any templates at all. Template are only a mechanism to make it more convenient to generate HTML.
If you thus make a request to the DetailView
, then this will not somehow include the CreateView
, it will simply let the DetailView
decide what should be done to generate a response and in this case that is rendering a template.
You can however easily use the FormMixin
[Django-doc] to render the form:
from django.views.generic.edit import FormMixin
class PostDetailView(FormMixin, LoginRequiredMixin, DetailView):
model = Post
form_class = CommentCreationForm
context_object_name = 'post'
template_name = 'post/details.html'
def post(self, request, *args, **kwargs):
form = self.get_form()
self.object = self.get_object()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.instance.author = self.request.user
form.instance.post = self.object
return super().form_valid(form)
Here we thus make use of the mixin to handle the logic to create a form and pass it to the context. We have to implement the post
method that will check if the form is valid, and if it is, adds the author
and the post
to the instance wrapped in the form.
Note: It is normally better to make use of the
settings.AUTH_USER_MODEL
[Django-doc] to refer to the user model, than to use theUser
model [Django-doc] directly. For more information you can see the referencing theUser
model section of the documentation.
Upvotes: 1