Getting all the users name who liked a post in django - python

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 %}

Related

News Feed hidden from users who aren't administrators

On my social media platform, the news feed (called post_list) seems to be hidden from any user that isn't an admin.
Even when text is entered into the box and 'post' is pressed, the page refreshes but the text box isn't emptied and no posts appear belowhand.
If I log in as an admin, the feed appears immediately and so do all the posts that I just posted from the non-admin account that didn't appear on the non-admin account. As shown here.
I have just recently added the ability to share posts, so maybe that has influenced this issue in some manner.
(The news feed) post_list.html:
> {% extends 'landing/base.html' %} {% load crispy_forms_tags %}
>
> {% block content %} <div class="container">
> <div class="row justify-content-center mt-3">
> <div class="col-md-5 col-sm-12 border-bottom">
> <h5>Create a Post</h5>
> </div>
> </div>
>
> <div class="row justify-content-center mt-3">
> <div class="col-md-5 col-sm-12 border-bottom">
> <form method="POST" enctype="multipart/form-data">
> {% csrf_token %}
> {{ form | crispy }}
> <div class="d-grid gap-2">
> <button class="btn btn-light" style="background-color: #CC64C3; mt-3 mb-5">Post</button>
> </div>
> </form>
> </div>
> </div>
>
> {% for post in post_list %}
> <div class="row justify-content-center mt-3">
> <div class="col-md-5 col-sm-12 border-bottom position-relative">
> <div>
> <a href="{% url 'profile' post.author.profile.pk %}">
> <img class="rounded-circle post-img" height="30" width="30" src="{{ post.author.profile.picture.url }}" />
> </a>
> <p class="post-text">
> <a class="text-primary post-link" href="{% url 'profile' post.author.profile.pk %}">#{{ post.author }}</a> {{
> post.created_on }}
> </p>
> </div>
> <div class="position-relative">
> <p>{{ post.body }}</p>
>
> {% if post.image.count > 0 %}
> <div class="row">
> {% for img in post.image.all %}
> <div class="col-md-4 col-xs-12">
> <img src="{{ img.image.url }}" class="post-image" />
> </div>
> {% endfor %}
> </div>
> {% endif %}
> <form method="POST" action="{% url 'share-post' post.pk %}" class="d-none" id="{{ post.pk }}">
> {% csrf_token %}
> {{ shareform | crispy }}
> <div class="d-grid gap-2">
> <button class="btn btn-light" style="background-color: #CC64C3; mt-3 mb-5">Share</button>
> </div>
> </form>
> </div>
>
> <div class="d-flex flex-row">
> <form method="POST" action="{% url 'like' post.pk %}">
> {% csrf_token %}
> <input type="hidden" name="next" value="{{ request.path }}">
> <button class="remove-default-btn" type="submit">
> <i class="far fa-thumbs-up"><span>{{ post.likes.all.count }}</span></i>
> </button>
> </form>
>
> <form method="POST" action="{% url 'dislike' post.pk %}">
> {% csrf_token %}
> <input type="hidden" name="next" value="{{ request.path }}">
> <button class="remove-default-btn" type="submit">
> <i class="far fa-thumbs-down"><span>{{ post.dislikes.all.count }}</span></i>
> </button>
> </form>
> <span onclick="shareToggle('{{ post.pk }}')"><i class="far fa-share-square share-btn"></i></span>
> </div>
> </div>
> {% endfor %} </div> {% endblock content %}
views.py:
from django.shortcuts import render, redirect
from django.db.models import Q
from django.utils import timezone
from django.urls import reverse_lazy
from django.shortcuts import redirect
from django.contrib import messages
from django.contrib.auth.models import User
from django.http import HttpResponseRedirect, HttpResponse
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
from django.views import View
from django.views.generic.edit import UpdateView, DeleteView
from .models import MessageModel, Post, Comment, UserProfile, Notification, ThreadModel, MessageModel, Image
from .forms import PostForm, CommentForm,ThreadForm, MessageForm, ShareForm
class PostListView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
logged_in_user = request.user
posts = Post.objects.filter(
author__profile__followers__in=[logged_in_user.id]
).order_by('-created_on')
form = PostForm()
share_form = ShareForm()
context = {
'post_list': posts,
'shareform': share_form,
'form': form,
}
return render(request, 'social/post_list.html', context)
def post(self, request, *args, **kwargs):
logged_in_user = request.user
posts = Post.objects.filter(
author__profile__followers__in=[logged_in_user.id]
).order_by('-created_on')
form = PostForm(request.POST, request.FILES)
files = request.FILES.getlist('image')
share_form = ShareForm()
if form.is_valid():
new_post = form.save(commit=False)
new_post.author = request.user
new_post.save()
for f in files:
img = Image(image=f)
img.save()
new_post.image.add(img)
new_post.save()
context = {
'post_list': posts,
'share_form': share_form,
'form': form,
}
return render(request, 'social/post_list.html', context)
class PostDetailView(LoginRequiredMixin, View):
def get(self, request, pk, *args, **kwargs):
post = Post.objects.get(pk=pk)
form = CommentForm()
comments = Comment.objects.filter(post=post).order_by('-created_on')
context = {
'post': post,
'form': form,
'comments': comments,
}
return render(request, 'social/post_detail.html', context)
def post(self, request, pk, *args, **kwargs):
post = Post.objects.get(pk=pk)
form = CommentForm(request.POST)
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.author = request.user
new_comment.post = post
new_comment.save()
comments = Comment.objects.filter(post=post).order_by('-created_on')
notification = Notification.objects.create(notification_type=2, from_user=request.user, to_user=post.author, post=post)
context = {
'post': post,
'form': form,
'comments': comments,
}
return render(request, 'social/post_detail.html', context)
class CommentReplyView(LoginRequiredMixin, View):
def post(self, request, post_pk, pk, *args, **kwargs):
post = Post.objects.get(pk=post_pk)
parent_comment = Comment.objects.get(pk=pk)
form = CommentForm(request.POST)
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.author = request.user
new_comment.post = post
new_comment.parent = parent_comment
new_comment.save()
notification = Notification.objects.create(notification_type=2, from_user=request.user, to_user=parent_comment.author, comment=new_comment)
return redirect('post-detail', pk=post_pk)
class PostEditView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields =['body']
template_name = 'social/post_edit.html'
def get_success_url(self):
pk = self.kwargs['pk']
return reverse_lazy('post-detail', kwargs={'pk': pk})
def test_func(self):
post = self.get_object()
return self.request.user == post.author
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
template_name = 'social/post_delete.html'
success_url = reverse_lazy('post-list')
def test_func(self):
post = self.get_object()
return self.request.user == post.author
class CommentDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Comment
template_name = 'social/comment_delete.html'
def get_success_url(self):
pk = self.kwargs['post_pk']
return reverse_lazy('post-detail', kwargs={'pk': pk})
def test_func(self):
post = self.get_object()
return self.request.user == post.author
class ProfileView(View):
def get(self, request, pk, *args, **kwargs):
profile = UserProfile.objects.get(pk=pk)
user = profile.user
post = Post.objects.filter(author=user).order_by('-created_on')
followers = profile.followers.all()
if len(followers) == 0:
is_following = False
for follower in followers:
if follower == request.user:
is_following = True
break
else:
is_following = False
number_of_followers = len(followers)
context = {
'user': user,
'profile': profile,
'posts': post,
'number_of_followers': number_of_followers,
'is_following': is_following,
}
return render(request, 'social/profile.html', context)
class ProfileEditView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = UserProfile
fields = ['name', 'bio', 'birth_date','location','picture']
template_name = 'social/profile_edit.html'
def get_success_url(self):
pk = self.kwargs['pk']
return reverse_lazy('profile', kwargs={'pk':pk})
def test_func(self):
profile = self.get_object()
return self.request.user == profile.user
class AddFollower(LoginRequiredMixin, View):
def post(self, request, pk, *args, **kwargs):
profile = UserProfile.objects.get(pk=pk)
profile.followers.add(request.user)
notification = Notification.objects.create(notification_type=3, from_user=request.user, to_user=profile.user)
return redirect('profile', pk=profile.pk)
class RemoveFollower(LoginRequiredMixin, View):
def post(self, request, pk, *args, **kwargs):
profile = UserProfile.objects.get(pk=pk)
profile.followers.remove(request.user)
return redirect('profile', pk=profile.pk)
class AddLike(LoginRequiredMixin, View):
def post(self, request, pk, *args, **kwargs):
post = Post.objects.get(pk=pk)
is_dislike = False
for dislike in post.dislikes.all():
if dislike == request.user:
is_dislike = True
break
if is_dislike:
post.dislikes.remove(request.user)
is_like = False
for like in post.likes.all():
if like == request.user:
is_like = True
break
if not is_like:
post.likes.add(request.user)
notification = Notification.objects.create(notification_type=1, from_user=request.user, to_user=post.author, post=post)
if is_like:
post.likes.remove(request.user)
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)
class AddDislike(LoginRequiredMixin, View):
def post(self, request, pk, *args, **kwargs):
post = Post.objects.get(pk=pk)
is_like = False
for like in post.likes.all():
if like == request.user:
is_like = True
break
if is_like:
post.likes.remove(request.user)
is_dislike = False
for dislike in post.dislikes.all():
if dislike == request.user:
is_dislike = True
break
if not is_dislike:
post.dislikes.add(request.user)
if is_dislike:
post.dislikes.remove(request.user)
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)
class AddCommentLike(LoginRequiredMixin, View):
def post(self, request, pk, *args, **kwargs):
comment = Comment.objects.get(pk=pk)
is_dislike = False
for dislike in comment.dislikes.all():
if dislike == request.user:
is_dislike = True
break
if is_dislike:
comment.dislikes.remove(request.user)
is_like = False
for like in comment.likes.all():
if like == request.user:
is_like = True
break
if not is_like:
comment.likes.add(request.user)
notification = Notification.objects.create(notification_type=1, from_user=request.user, to_user=comment.author, comment=comment)
if is_like:
comment.likes.remove(request.user)
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)
class AddCommentDislike(LoginRequiredMixin, View):
def post(self, request, pk, *args, **kwargs):
comment = Comment.objects.get(pk=pk)
is_like = False
for like in comment.likes.all():
if like == request.user:
is_like = True
break
if is_like:
comment.likes.remove(request.user)
is_dislike = False
for dislike in comment.dislikes.all():
if dislike == request.user:
is_dislike = True
break
if not is_dislike:
comment.dislikes.add(request.user)
if is_dislike:
comment.dislikes.remove(request.user)
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)
class SharedPostView(View):
def post(self, request, pk, *args, **kwargs):
original_post = Post.objects.get(pk=pk)
form = ShareForm(request.POST)
if form.is_valid():
new_post = Post(
shared_body=self.request.POST.get('body'),
body=original_post.body,
author=original_post.author,
created_on=original_post.created_on,
shared_user=request.user,
shared_on=timezone.now(),
)
new_post.save()
for img in original_post.image.all():
new_post.image.add(img)
new_post.save()
return redirect ('post-list')
class UserSearch(View):
def get(self, request, *args, **kwargs):
query = self.request.GET.get('query')
profile_list = UserProfile.objects.filter(
Q(user__username__icontains=query)
)
context = {
'profile_list': profile_list,
}
return render(request, 'social/search.html', context)
class ListFollowers(View):
def get(self, request, pk, *args, **kwargs):
profile = UserProfile.objects.get(pk=pk)
followers = profile.followers.all()
context = {
'profile': profile,
'followers': followers,
}
return render(request, 'social/followers_list.html', context)
class PostNotification(View):
def get(self, request, notification_pk, post_pk, *args, **kwargs):
notification = Notification.objects.get(pk=notification_pk)
post = Post.objects.get(pk=post_pk)
notification.user_has_seen = True
notification.save()
return redirect('post-detail', pk=post_pk)
class FollowNotification(View):
def get(self, request, notification_pk, profile_pk, *args, **kwargs):
notification = Notification.objects.get(pk=notification_pk)
profile = UserProfile.objects.get(pk=profile_pk)
notification.user_has_seen = True
notification.save()
return redirect('profile', pk=profile_pk)
class ThreadNotification(View):
def get(self, request, notification_pk, object_pk, *args, **kwargs):
notification = Notification.objects.get(pk=notification_pk)
thread = ThreadModel.objects.get(pk=object_pk)
notification.user_has_seen = True
notification.save()
return redirect('thread', pk=object_pk)
class RemoveNotification(View):
def delete(self, request, notification_pk, *args, **kwargs):
notification = Notification.objects.get(pk=notification_pk)
notification.user_has_seen = True
notification.save()
return HttpResponse('Success', content_type='text/plain')
class ListThreads(View):
def get(self, request, *args, **kwargs):
threads = ThreadModel.objects.filter(Q(user=request.user) | Q(receiver=request.user))
context = {
'threads': threads
}
return render(request, 'social/inbox.html', context)
class CreateThread(View):
def get(self, request, *args, **kwargs):
form = ThreadForm()
context = {
'form': form
}
return render(request, 'social/create_thread.html', context)
def post(self, request, *args, **kwargs):
form = ThreadForm(request.POST)
username = request.POST.get('username')
try:
receiver = User.objects.get(username=username)
if ThreadModel.objects.filter(user=request.user, receiver=receiver).exists():
thread = ThreadModel.objects.filter(user=request.user, receiver=receiver)[0]
return redirect('thread', pk=thread.pk)
elif ThreadModel.objects.filter(user=receiver, receiver=request.user).exists():
thread = ThreadModel.objects.filter(user=receiver, receiver=request.user)[0]
return redirect('thread', pk=thread.pk)
if form.is_valid():
thread = ThreadModel(
user=request.user,
receiver=receiver
)
thread.save()
return redirect('thread', pk=thread.pk)
except:
messages.error(request, 'User not found')
return redirect('create-thread')
class ThreadView(View):
def get(self, request, pk, *args, **kwargs):
form = MessageForm()
thread = ThreadModel.objects.get(pk=pk)
message_list = MessageModel.objects.filter(thread__pk__contains=pk)
context = {
'thread': thread,
'form': form,
'message_list': message_list,
}
return render(request, 'social/thread.html', context)
class CreateMessage(View):
def post(self, request, pk, *args, **kwargs):
form = MessageForm(request.POST, request.FILES)
thread = ThreadModel.objects.get(pk=pk)
if thread.receiver == request.user:
receiver = thread.user
else:
receiver = thread.receiver
if form.is_valid():
message = form.save(commit=False)
message.thread = thread
message.sender_user = request.user
message.receiver_user = receiver
message.save()
notification = Notification.objects.create(
notification_type=4,
from_user=request.user,
to_user=receiver,
thread=thread
)
return redirect('thread', pk=pk)
models.py:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class Post(models.Model):
shared_body = models.TextField(blank=True, null=True)
body = models.TextField()
image = models.ManyToManyField('Image', blank=True)
created_on = models.DateTimeField(default=timezone.now)
shared_on = models.DateTimeField(blank=True, null=True)
shared_user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name='+')
author = models.ForeignKey(User, on_delete=models.CASCADE)
likes = models.ManyToManyField(User, blank=True, related_name='likes')
dislikes = models.ManyToManyField(User, blank=True, related_name='dislikes')
class Meta:
ordering = ['-created_on', '-shared_on']
class Comment(models.Model):
comment = models.TextField()
created_on = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey('Post', on_delete=models.CASCADE, null=True)
likes = models.ManyToManyField(User, blank=True, related_name='comment_likes')
dislikes = models.ManyToManyField(User, blank=True, related_name='comment_dislikes')
parent = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True, related_name='+')
#property
def children(self):
return Comment.objects.filter(parent=self).order_by('-created_on').all()
#property
def is_parent(self):
if self.parent is None:
return True
return False
class UserProfile(models.Model):
user = models.OneToOneField(User, primary_key=True, verbose_name='user', related_name='profile', on_delete=models.CASCADE)
name = models.CharField(max_length=30, blank=True, null=True)
bio = models.TextField(max_length=500, blank=True, null=True)
birth_date = models.DateField(null=True, blank=True)
location = models.CharField(max_length=100, blank=True, null=True)
picture = models.ImageField(upload_to='uploads/profile_pictures', default='uploads/profile_pictures/default.jpeg', blank=True)
followers = models.ManyToManyField(User, blank=True, related_name='followers')
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
class Notification(models.Model):
# 1 = Like, 2 = Comment, 3 = Follow, 4= DM
notification_type = models.IntegerField()
to_user = models.ForeignKey(User, related_name='notification_to', on_delete=models.CASCADE, null=True)
from_user = models.ForeignKey(User, related_name='notification_from', on_delete=models.CASCADE, null=True)
post = models.ForeignKey('Post', on_delete=models.CASCADE, related_name='+', blank=True, null=True)
comment = models.ForeignKey('Comment', on_delete=models.CASCADE, related_name='+', blank=True, null=True)
thread = models.ForeignKey('ThreadModel', on_delete=models.CASCADE, related_name='+', blank=True, null=True)
date = models.DateTimeField(default=timezone.now)
user_has_seen = models.BooleanField(default=False)
class ThreadModel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='+')
receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name='+')
class MessageModel(models.Model):
thread = models.ForeignKey('ThreadModel', related_name='+', on_delete=models.CASCADE, blank=True, null=True)
sender_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='+')
receiver_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='+')
body = models.CharField(max_length=10000)
image = models.ImageField(upload_to='uploads/message_photos', blank=True, null=True)
date = models.DateTimeField(default=timezone.now)
is_read = models.BooleanField(default=False)
class Image(models.Model):
image = models.ImageField(upload_to='uploads/post_photos', blank=True, null=True)
Any tips as to why the news feed may only be appearing on the admin's account/ only appears AFTER a post has been submitted (which would be a nuisance to have to submit a post every time you want to view your news feed) would be greatly appreciated!
Does this issue occur even when you remove the filter:
posts = Post.objects.filter(
author__profile__followers__in=[logged_in_user.id]
).order_by('-created_on')
It looks like it only shows posts for the followers of the user.id
Firstfully, you should not end post() method with render. That may cause weird stuff happening during site loading. Rather use return self.form_valid(form) or the same with invalid. It's possibly, that you might need to inherit also FormMixin. Then you need to specify get_success_url() but I can see you know how to do that.
Secondly, if you want PostListView to be a list view, do it :) Then use get_queryset() method:
class PostListView(LoginRequiredMixin, ListView):
...
def get_queryset(self):
return Post.objects.filter(...)
Thirdly, I am not sure about author__profile__followers__in=[logged_in_user.id] filter. For me it is confusing. Maybe try different approach here to fix filtering. Try .all() instead of .filter() and see if it shows all correctly.
It seems you may be confused with ManyToMany relations. You should not use related name same as field name, it works exactly in a opposite way, as you might think. Read about it in Django's Docs.

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 over ride the get context data method in view

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

How to make the post title available at my template

i need to know how i can make the actual postname a comment belongs to available at my template to display it later on:
views.py
def comment_edit(request, pk):
comment = get_object_or_404(Comment, pk=pk)
if request.user == comment.author:
if request.method == "POST":
form = CommentForm(request.POST, instance=comment)
if form.is_valid():
comment = form.save(commit=False)
comment.author = request.user
comment.published_date = timezone.now()
comment.save()
return redirect('post_detail', pk=comment.post.pk)
else:
form = CommentForm(instance=comment)
return render(request, 'app/Post/post_comment_edit.html', {'form': form})
else:
return redirect('post_detail', pk=comment.post.pk)
template.html:
{{ post.category.title }}
{{ post.title }}
models.py
class Comment(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
content = models.TextField(max_length=500)
published_date = models.DateField(auto_now_add=True, null=True)
thanks in advance
pass the comment instance to your template
return render(request, 'app/Post/post_comment_edit.html', {'form': form, 'comment': comment})
and in template
{{ comment.post.category.title }}
{{ comment.post.title }}

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