How to over ride the get context data method in view - python

I am currently trying to create a like button for my posts in Django
I have reached to the part where I can add a like but I am facing difficulty writing the code related to the view which linking the PostListView if there is user who liked it or not. I am getting an error:
Exception Value:
name 'post' is not defined
Here is my Model:
class Post(models.Model):
designer = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
date_posted = models.DateTimeField(default=timezone.now)
likes = models.ManyToManyField(User, blank=True, related_name='likes')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("score:post-detail", kwargs={'pk': self.pk})
Here is my URL
path('like/', like_post, name='like_post'),
Here is the updated views code:
class PostListView(ListView):
model = Post
template_name = "score.html"
ordering = ['-date_posted']
context_object_name = 'posts'
queryset = Post.objects.filter(admin_approved=True)
paginate_by = 5
def get_context_data(self, **kwargs):
post = get_object_or_404(Post, id=self.request.POST.get('post_id'))
context = super(PostListView, self).get_context_data(**kwargs)
context['posts'][0].likes.filter(id=self.request.user.id).exists()
is_liked = False
if post.likes.filter(id=self.request.user.id).exists():
is_liked = True
context['is_like'] = is_liked
return context
def like_post(request):
post = get_object_or_404(Post, id=request.POST.get('post_id'))
is_liked = False
if post.likes.filter(id=request.user.id).exists():
posts.likes.remove(request.user)
is_liked = False
else:
post.likes.add(request.user)
is_liked = True
return HttpResponseRedirect(post.get_absolute_url())
here is the template
{% extends "base.html"%} {% block content %} {% for post in posts %}
<div style="padding-top: 200 px;"><strong>{{post.title}}</strong></div>
<form action="{% url 'score:like_post'%}" method="POST" class="ui form">
{% csrf_token %} {% if is_like %}
<input type="hidden" name="post_id" value="{{post.id}}" />
<button class="ui button positive" type="submit">Unlike</button>
{% else %}
<button class="ui button negative" type="submit">Like</button>
{% endif %}
</form>
<strong>Likes </strong>
{% endfor %} {% endblock content %}

class PostListView(ListView):
model = Post
template_name = "score.html"
ordering = ['-date_posted']
context_object_name = 'posts'
queryset = Post.objects.filter(admin_approved=True)
paginate_by = 5
def get_context_data(self, **kwargs):
context = super(PostListView, self).get_context_data(**kwargs) _____________________
is_liked = False |
if post.likes.filter(id=request.user.id).exists(): <-----| I Think the issue is
is_liked = True | with this code
context = {'post': post, |
'is_like': is_liked, |
} |_____________________
return context
like you mentioned, the issue is in this code,
post.likes.filter(id=request.user.id).exists():
this line causes the error. you are calling post.likes.filter , but you haven't defined a variable post.
since the view is a ListView , you can get list of all posts from context['posts'] after the super method. and you can call context['posts'][0].likes.filter(id=self.request.user.id).exists() to get the details of first post,
or if you want to check for a specific post, use DetailView instead of ListView
Hope this helps
Edit:
class PostListView(ListView):
model = Post
template_name = "score.html"
ordering = ['-date_posted']
context_object_name = 'posts'
queryset = Post.objects.filter(admin_approved=True)
paginate_by = 5
def get_context_data(self, **kwargs):
post = get_object_or_404(Post, id=self.request.POST.get('post_id'))
context = super(PostListView, self).get_context_data(**kwargs)
context['posts'][0].likes.filter(id=self.request.user.id).exists()
is_liked = False
if post.likes.filter(id=self.request.user.id).exists():
is_liked = True
context['is_like'] = is_liked
return context
replace the above code with the below code.
class PostListView(ListView):
model = Post
template_name = "score.html"
ordering = ['-date_posted']
context_object_name = 'posts'
queryset = Post.objects.filter(admin_approved=True)
paginate_by = 5
def get_context_data(self, **kwargs):
context = super(PostListView, self).get_context_data(**kwargs)
post = context['posts'][0]
is_liked = False
if post.likes.filter(id=self.request.user.id).exists():
is_liked = True
context['current_post'] = post
context['is_like'] = is_liked
return context

Related

Getting all the users name who liked a post in django

I am trying to show the List of Users who Liked a Particular Post. Here is what I have tried but nothing is showing.
I have created the post_likes in the views.py and tried to loop through its users in the post-details.html:
Here is the post_detail.html template:
{% for user in post_likes %}
<p>{{ user.username }}f</p>
{% endfor %}
but nothing is showing.
Here is the Post Models.py:
class Post(models.Model):
content = RichTextUploadingField(null=True, blank=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='author')
likes = models.ManyToManyField(User, related_name='liked', blank=True)
Here are the like model.py:
class Like(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
value = models.CharField(choices=LIKE_CHOICES, default='Like', max_length=8)
Here are the views.py:
class PostDetailView(DetailView):
model = Post
template_name = "blog/post_detail.html" # <app>/<model>_<viewtype>.html
def get_context_data(self, *args, **kwargs):
context = super(PostDetailView, self).get_context_data()
post = get_object_or_404(Post, slug=self.kwargs['slug'])
comments = Comment.objects.filter(
post=post).order_by('-id')
total_likes = post.total_likes()
liked = False
if post.likes.filter(id=self.request.user.id).exists():
liked = True
if self.request.method == 'POST':
comment_form = CommentForm(self.request.POST or None)
--------Comment Related Lines--------------------------------
else:
comment_form = CommentForm()
context["comments"] = comments
context["comment_form"] = comment_form
context["total_likes"] = total_likes
context["liked"] = liked
return context
def get(self, request, *args, **kwargs):
res = super().get(request, *args, **kwargs)
self.object.incrementViewCount()
if self.request.is_ajax():
context = self.get_context_data(self, *args, **kwargs)
html = render_to_string('blog/comments.html', context, request=self.request)
return JsonResponse({'form': html})
return res
def LikeView(request):
post = get_object_or_404(Post, id=request.POST.get('id'))
liked = False
current_likes = post.num_likes
user = request.user
if post.author.id == request.user.id:
messages.warning(request, 'You can not like you own Post')
else:
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
liked = False
current_likes = current_likes - 1
else:
post.likes.add(request.user)
liked = True
current_likes = current_likes + 1
post.num_likes = current_likes
post.save()
like, created = Like.objects.get_or_create(user=user, post=post)
if not created:
if like.value == 'Like':
like.value = 'Unlike'
else:
like.value = 'Like'
like.save()
context = {
'total_likes': post.total_likes,
'liked': liked,
'post': post
}
if request.is_ajax:
html = render_to_string('blog/like_section.html', context, request=request)
return JsonResponse({'form': html})
def post_likes(request, self):
posts = get_object_or_404(Post, slug=self.kwargs['slug'])
post_likes = posts.likes.all()
context = {'post_likes': post_likes, }
return render(request, 'blog/post_detail.html', context)
my question is:
How can I see the usernames who liked the particular post?
In your template, replace
{% for user in post_likes %}
<p>{{ user.username }}f</p>
{% endfor %}
with
{ % for like in post_likes %}
<p> {{ like.user.username }} </p>
{ % endfor %}

If there are no Posts displayed, how can I put a message?

In this situation I'm creating a blog, and in this blog I'm creating a "My Posts" page, and the thing is that if a user hasn't created a post, I want it to say the message "You have not written any posts yet", I'm having problems with the logic in the html, I was trying to use {% if post %}, but it's not working, here's the code:
my_posts.html
{% extends "app1/base.html" %}
{% block body_block %}
<div class="container">
<h1>Post</h1>
{% for post in object_list %}
{% empty %}
<h1>You have not written any posts yet!</h1>
{% if user.is_authenticated %}
{% if user.id == post.author.id %}
<li>{{post.title}} -
{{post.author}} - <small>{{post.post_date}}</small> - <small> category : {{post.category}} - </small>
<small>Edit</small><small>
- Delete
</small></li>
{{post.snippet}}
{% endif %}
{% endif %}
{% endfor %}
</div>
{% endblock %}
views.py
from django.shortcuts import render, get_object_or_404
from django.contrib.auth import authenticate, login, logout
from django.urls import reverse, reverse_lazy
from .forms import PostForm, PostUpdateForm
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from .models import Post, Category
from django.http import HttpResponseRedirect
# Create your views here.
def index(request):
return render(request, 'app1/index.html')
def LikeView(request, pk):
post = get_object_or_404(Post, id=request.POST.get('post_id'))
liked = False
if post.likes.filter(id = request.user.id).exists():
post.likes.remove(request.user)
liked = False
else:
post.likes.add(request.user)
liked = True
return HttpResponseRedirect(reverse('app1:article-detail', args = [str(pk),]))
class PostView(ListView):
model = Post
template_name = 'app1/post.html'
ordering = ['-post_date']
def get_context_data(self, *args, **kwargs):
cat_menu = Category.objects.all()
context = super(PostView, self).get_context_data(*args, **kwargs)
context["cat_menu"] = cat_menu
return context
def CategoryView(request, cats):
category_posts = Post.objects.filter(category=cats.replace('-', ' '))
return render(request, 'app1/categories.html', {'cats':cats.title().replace('-', ' '), 'category_posts': category_posts})
def CategoryListView(request):
cat_menu_list = Category.objects.all()
return render(request, 'app1/category_list.html', {"cat_menu_list":cat_menu_list})
class ArticleDetailView(DetailView):
model = Post
template_name = 'app1/article_details.html'
def get_context_data(self, *args, **kwargs):
context = super(ArticleDetailView, self).get_context_data(*args, **kwargs)
stuff = get_object_or_404(Post, id = self.kwargs['pk'])
liked = False
if stuff.likes.filter(id = self.request.user.id).exists():
liked = True
total_likes = stuff.total_likes()
context["total_likes"] = total_likes
context["liked"] = liked
return context
class AddPostView(CreateView):
model = Post
form_class = PostForm
template_name = 'app1/createpost.html'
#fields = '__all__'
class UpdatePostView(UpdateView):
model = Post
form_class = PostUpdateForm
template_name = 'app1/update_post.html'
class DeletePostView(DeleteView):
model = Post
template_name = 'app1/delete_post.html'
success_url = reverse_lazy('index')
class AddCategoryView(CreateView):
model = Category
template_name = 'app1/add_category.html'
fields = '__all__'
success_url = reverse_lazy('app1:Post')
class MyPostsView(ListView):
model = Post
template_name = 'app1/my_posts.html'
models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from datetime import datetime, date
from ckeditor.fields import RichTextField
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length= 255)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('index')
class Profile(models.Model):
user = models.OneToOneField(User, null = True, on_delete=models.CASCADE)
bio = models.TextField()
profile_pic = models.ImageField(null = True, blank = True, upload_to = "images/profile/")
website_url = models.CharField(max_length= 255, blank = True, null = True)
facebook_url = models.CharField(max_length= 255, blank = True, null = True)
twitter_url = models.CharField(max_length= 255, blank = True, null = True)
instagram_url = models.CharField(max_length= 255, blank = True, null = True)
pinterest_url = models.CharField(max_length= 255, blank = True, null = True)
def __str__(self):
return str(self.user)
class Post(models.Model):
title = models.CharField(max_length= 255)
header_image = models.ImageField(null = True, blank = True, upload_to = 'images/')
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = RichTextField(blank = True, null = True)
#body = models.TextField()
post_date = models.DateField(auto_now_add=True)
category = models.CharField(max_length=255, default='coding')
snippet = models.CharField(max_length=255)
likes = models.ManyToManyField(User, related_name = 'blog_posts')
def total_likes(self):
return self.likes.count()
def __str__(self):
return self.title + ' | ' + str(self.author)
def get_absolute_url(self):
return reverse('app1:article-detail', args=(self.id,))
I would really appreciate your help and thanks in advance!
You can use the {% empty %} tag in the for loop.
{% for post in object_list %}
...
{% empty %}
<h1>You have not written any posts yet!</h1>
{% endfor %}
OR you can use simply the if else inside the template like this.
{% if object_list %}
{% for post in object_list %}
...
{% endfor %}
{% else %}
<h1>You have not written any posts yet!</h1>
{% endif %}

Getting error 405 while using ModelFormMixin with DetailView

I want to create a DetailView page which displays the detail of a model but I want to add a Comment section in the DetailView page using ModelFormMixin.
This is my views.py code:
class PostDetailView(ModelFormMixin, DetailView):
model = UserPost
context_object_name='post_detail'
form_class = UserCommentForm
def get_context_data(self, *args, **kwargs):
context = super(PostDetailView, self).get_context_data(*args, **kwargs)
context['form'] = self.get_form()
return context
def get_absolute_url(self):
return reverse(request, 'basic_app:post_detail', kwargs={'pk':self.pk})
But when I hit the submit button it shows the following error:
Edited part:
This is my views.py file
model.py
forms.py
userpost_detail.html
browser image before clicking enter button
browser image after clicking enter button
django admin page
I'm sorry for not uploading the actual code because it was too difficult to upload that bulk of code.
I think the following code will help you. I code it a long time ago, but it seems to solve your problem (I didn't use taggit, so I created a PostTag model):
Models:
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.timezone import localtime
from django.urls import reverse
class User(AbstractUser):
pass
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status='published')
class PostTag(models.Model):
name = models.CharField(max_length=40)
slug = models.SlugField(max_length=40)
def __str__(self):
return self.name
class Post(models.Model):
POST_STATUS = (('draft', 'Draft'), ('published', 'Published'))
title = models.CharField(max_length=100)
body = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')
created = models.DateTimeField(auto_now_add=True)
publish = models.DateTimeField(auto_now=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=100, unique_for_date='publish')
status = models.CharField(max_length=10, choices=POST_STATUS, default='draft')
tags = models.ManyToManyField(PostTag, blank=True)
def get_absolute_url(self):
local_time = localtime(self.publish)
return reverse("blog:post_date_detail", args=[local_time.year, local_time.month, local_time.day, self.slug])
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
objects = models.Manager() # The default manager.
published = PublishedManager() # Custom manager.
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
def get_absolute_url(self):
local_time = localtime(self.post.publish)
return reverse("blog:post_date_detail", args=[local_time.year, local_time.month, local_time.day, self.post.slug])
class Meta:
ordering = ('created',)
def __str__(self):
return f'Comment by {self.name} on {self.post}'
Views:
from django.shortcuts import render, get_object_or_404, HttpResponseRedirect
from django.views.generic import ListView, DetailView, View
from django.views.generic.edit import FormView, SingleObjectMixin, CreateView
from django.views.generic.dates import YearArchiveView, MonthArchiveView, DateDetailView
from django.core.mail import send_mail
from django.db.models import Count
from .models import Post, User, Comment, PostTag
from .forms import EmailPostForm, CommentForm
class PostListView(ListView):
queryset = Post.published.all()
context_object_name = 'posts'
paginate_by = 4
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# si hay kwargs se actualiza el context
if self.kwargs:
context["tag"] = self.kwargs['tag_slug']
return context
def get_queryset(self):
tag = None
if self.kwargs:
tag_slug = self.kwargs['tag_slug']
tag = get_object_or_404(PostTag, slug=tag_slug)
posts = self.queryset.filter(tags__in=[tag])
return posts
return self.queryset
class PostYearArchiveView(YearArchiveView):
queryset = Post.published.all()
template_name = 'blog/post_list.html'
date_field = "publish"
context_object_name = 'posts'
make_object_list = True
paginate_by = 4
class PostMonthArchiveView(MonthArchiveView):
queryset = Post.published.all()
template_name = 'blog/post_list.html'
date_field = "publish"
context_object_name = 'posts'
month_format='%m'
paginate_by = 4
class PostDateDetailView(DateDetailView):
queryset = Post.published.all()
date_field = "publish"
month_format='%m'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
obj = self.get_object()
post_tags_pks = obj.tags.all().values_list('pk', flat=True)
related_posts = self.queryset.filter(tags__in=post_tags_pks).exclude(pk=obj.pk)
related_posts = related_posts.annotate(same_tags=Count('tags')).order_by('-same_tags','-publish')[:3]
context["related_posts"] = related_posts
comments = obj.comments.filter(active=True)
context["comments"] = comments
context['post_id'] = obj.pk
context['form'] = CommentForm()
return context
class NewComment(CreateView):
model = Comment
template_name = 'blog/post_detail.html'
form_class = CommentForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
post = context["form"].instance.post
context['post'] = post
post_tags_pks = post.tags.all().values_list('pk', flat=True)
related_posts = Post.published.filter(tags__in=post_tags_pks).exclude(pk=post.pk)
related_posts = related_posts.annotate(same_tags=Count('tags')).order_by('-same_tags','-publish')[:3]
context["related_posts"] = related_posts
comments = post.comments.filter(active=True)
context["comments"] = comments
return context
class PostDetail(View):
def get(self, request, *args, **kwargs):
view = PostDateDetailView.as_view()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
view = NewComment.as_view()
return view(request, *args, **kwargs)
class SharePostView(SingleObjectMixin, FormView):
form_class = EmailPostForm
template_name = 'blog/post_share.html'
success_url = '/blog'
context_object_name = 'posts'
queryset = Post.published.all()
def get(self, request, *args, **kwargs):
post = self.get_object()
context = {'post': post, 'form': self.form_class}
return render(request, self.template_name, context)
def form_valid(self, form):
post = self.get_object()
post_url = self.request.build_absolute_uri(post.get_absolute_url())
form.send_mail(post, post_url)
return super(SharePostView, self).form_valid(form)
Considerations: See get_context_data to add other data to the context: in this case tags, related_post, the form, etc...
I have used 3 views. DateDetailView (similar to your DetailView) to display the page (with the context needed).
CreateView to manage the POST method and save the comment into the DB. I have also added context to get the post information.
Finally a View with the intention of managing the same URL,but calling the appropiate view
when the request is GET or POST. See urls.py
URLS:
from django.urls import path
from blog import views
from blog.models import Post
app_name = 'blog'
urlpatterns = [
path("", views.PostListView.as_view(), name="post_list"),
path('tag/<slug:tag_slug>/', views.PostListView.as_view(), name='post_list_by_tag'),
path('<int:year>/', views.PostYearArchiveView.as_view(), name="post_year_archive"),
path('<int:year>/<int:month>/', views.PostMonthArchiveView.as_view(), name="post_month_numeric"),
path('<int:year>/<int:month>/<int:day>/<slug:slug>/', views.PostDetail.as_view(), name="post_date_detail"),
path('<int:pk>/share/', views.SharePostView.as_view(), name='post_share'),
]
Comment form:
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('name', 'email', 'body', 'post')
widgets = {
'name': forms.TextInput(attrs={'placeholder': 'Name'}),
'email': forms.EmailInput(attrs={'placeholder': 'E-mail'}),
'body': forms.Textarea(attrs={'placeholder': 'Write your message here'}),
'post' : forms.HiddenInput(),
}
form in template:
<form method="post" action="" novalidate>
{% csrf_token %}
<div class="input-group input-group-icon">
{{ form.name }}
<div class="input-icon"><i class="fas fa-user"></i></div>
{% if form.name.errors %}
{{form.name.errors}}
{% endif %}
</div>
<div class="input-group input-group-icon">
{{form.email }}
<div class="input-icon">
<i class="fas fa-envelope"></i>
</div>
{% if form.email.errors %}
{{form.email.errors}}
{% endif %}
</div>
<div class="msg">
<div class="input-group">{{form.body}}
{% if form.body.errors %}
{{form.body.errors}}
{% endif %}
</div>
</div>
<input type="hidden" name="post" value="{{ post.pk }}">
<div class="input-group send-reset">
<input type="submit" value="Enviar Comentario" />
</div>
</form>
Considerations: See the input type=hidden to get the post.pk. This is needed to save the comment.post field.
I think I covered all the issues you can have. Hope it helps!!

why the {% if post.is_liked %} doesn't work in home.html

I have passed the context of is_liked to from the PostListView to the home template, but why the if post.is_liked the statement doesn't work? I have an like_post function that when the user liked the post, the is_liked will equal to true and text will turn from not liked to liked. But why the if statements did not work(only showed not liked) in the template with no error messages? Or I have tried to change the if statements to {% post.user.is_liked %} and {% user.is_liked %}. But it still didn't work, what is the problem? thanks
models.py
class Post(models.Model):
title = models.CharField(max_length=100)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
likes = models.ManyToManyField(User, related_name='likes', blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
views.py
def home(request):
context = {
'posts': Post.objects.all(),
}
return render(request, 'blog/home.html', context)
def like_post(request): # post like
post = get_object_or_404(Post, id=request.POST.get('post_id'))
is_liked = False
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
is_liked = False
else:
post.likes.add(request.user)
is_liked = True
return HttpResponseRedirect(post.get_absolute_url())
class PostListView(ListView):
model = Post
template_name = 'blog/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 10
is_liked = False
def get_context_data(self, *, object_list=None, **kwargs):
context = super(PostListView, self).get_context_data()
posts = context['posts']
for post in posts:
if post.likes.filter(id=self.request.user.id).exists():
context['is_liked'] = True
return context
class PostDetailView(DetailView):
model = Post
is_liked = False
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
post = context['post']
if post.likes.filter(id=self.request.user.id).exists():
context['is_liked'] = True
return context
home.html
{% for post in posts %}
<form action="{% url 'like_post' %}" method="post">
{% csrf_token %}
{% if post.is_liked %} #I want to get whether the post is_liked by user
<h5>liked</h5>
{% else %}
<h5>not liked</h5>
{% endif %}
</form>
{% endfor %}
You can annotate the queryset such that the Post objects that arise from this have an extra attribute .is_liked with an Exists subquery [Django-doc]:
from django.db.models import Exists, OuterRef
class PostListView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 10
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).annotate(
is_liked=Exists(Post.likes.through.objects.filter(
user_id=self.request.user.id,
post_id=OuterRef('pk')
))
)

How to add a comment to post? PostDetailVew, Django 2.1.5

I want add comment to post on his page ("post detail" page).
I was find answer, but it create comment on other page. I want create comment on page of "post detail".
urls.py
url(r'^post/(?P<pk>\d+)/create/$', views.CommentCreate.as_view(), name='comment_create'),
models.py
class Comment(models.Model):
description = RichTextUploadingField()
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
comment_date = models.DateTimeField(auto_now_add=True, null=True)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
class Meta:
ordering = ["-comment_date"]
def __str__(self):
return "{}".format(self.description)
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['description']
views.py
class PostDetailView(generic.DetailView):
model = Post
class CommentCreate(LoginRequiredMixin, CreateView):
model = Comment
fields = ['description']
def get_context_data(self, **kwargs):
context = super(CommentCreate, self).get_context_data(**kwargs)
context['post'] = get_object_or_404(Post, pk = self.kwargs['pk'])
return context
def form_valid(self, form):
form.instance.author = self.request.user
form.instance.post=get_object_or_404(Post, pk = self.kwargs['pk'])
return super(CommentCreate, self).form_valid(form)
def get_success_url(self):
return reverse('post-detail', kwargs={'pk': self.kwargs['pk'],})
comment_form.html
...
<form action="" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<button type="submit">Submit</button>
</form>
...
post_detail.html
...
{% for comment in post.comment_set.all %}
<p>{{ comment.author }} ({{ comment.comment_date }}) {{ comment.description|safe }}</p>
{% endfor %}
<hr>
{% if user.is_authenticated %}
<p>Add a new comment</p>
...
I think, "comment_form" need to redirect to "post_detail", not generate new page for comment form.
And сould you tell, which parameters has a RichTextField (CKE), how change width, height field only in comment?
If you want the comment form right in your detail page then all you have to do is to add the form and post function in your View,
class PostDetailView(DetailView):
model = Post
template_name = 'yourdetailpage.html'
def get_context_data(self, **kwargs):
context = super(PostDetailView, self).get_context_data(**kwargs)
context['commentform'] = CommentForm()
return context
def post(self, request, pk):
post = get_object_or_404(Post, pk=pk)
form = CommentForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.post = post
obj.author = self.request.user
obj.save()
return redirect('detail', post.pk)
And now you can add your form in your html. And add a submit button to post comment.

Categories