Issue
I need to check if a user has liked a post on a page that displays all posts, I am passing the posts and user's likes below
def index(request):
if request.method == "POST":
text = request.POST["post-text"]
Post.objects.create(
entity = Entity.objects.create(
user = request.user,
text = text
)
)
return HttpResponseRedirect(reverse("index"))
return render(request, "network/index.html", {
"posts" : Post.objects.all().order_by('-entity__date', '-entity__id'),
"likes" : Like.objects.filter(user = request.user)
})
this is the model
class Entity(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="posts")
text = models.TextField()
date = models.DateTimeField(default=datetime.now())
class Like(models.Model):
entity = models.ForeignKey(Entity, on_delete=models.CASCADE, related_name="likes")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="likes")
class Post(models.Model):
entity = models.ForeignKey(Entity, on_delete=models.CASCADE, related_name="post")
Template:
{% for post in posts %}
<div>
<div>{{post.entity.user}}</div>
<div>{{post.entity.text}}</div>
<div>{{post.entity.date}}</div>
<div class="like-btn d-inline" data-id="{{post.entity.id}}">
{% if post.entity in likes %}
<p>yes</p>
{%else%}
<p>no</p>
{%endif%}
<div class="d-inline">{{post.entity.likes.count}}</div>
</div>
<br />
<a href="#">Comment</a>
<hr />
</div>
{% endfor %}
I don't know how to write the if condition, I've tried this {% if post.entity in likes %} but it doesn't work.
Solution
Please don't. While this can be done with such condition, it would result in a lot of extra queries. You can work with a Exists
subquery [Django-doc]:
from django.contrib.auth.decorators import login_required
from django.db.models import Exists, OuterRef
from django.shortcuts import redirect
@login_required
def index(request):
if request.method == 'POST':
text = request.POST['post-text']
Post.objects.create(
entity = Entity.objects.create(
user = request.user,
text = text
)
)
return redirect('index')
posts = Post.objects.annotate(
is_liked=Exists(
Like.objects.filter(user=request.user, entity_id=OuterRef('entity_id')
)
).select_related('entity').order_by('-entity__date', '-entity__id')
return render(request, "network/index.html", {
'posts' : posts
})
The Post
objects will then have an extra attribute .is_liked
that is True
if that Post
is liked by the logged in user.
Note: You can limit views to a view to authenticated users with the
@login_required
decorator [Django-doc].
Note: You can make use of
redirect(…)
[Django-doc] instead of first callingreverse(…)
[Django] and then wrap it in aHttpResponseRedirect
object [Django-doc]. Theredirect(…)
function does not only offer a more convenient signature to do this, it also for example will use the.get_absolute_url()
method [Django-doc] if you pass it a model object.
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.
Note: Django's
DateTimeField
[Django-doc] has aauto_now_add=…
parameter [Django-doc] to work with timestamps. This will automatically assign the current datetime when creating the object, and mark it as non-editable (editable=False
), such that it does not appear inModelForm
s by default.
Answered By - Willem Van Onsem
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.