Как проверить, находится ли объект в другом наборе запросов

Мне нужно проверить, понравилось ли пользователю сообщение на странице, которая отображает все сообщения, я передаю сообщения и лайки пользователя ниже

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

это модель

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")

Шаблон:

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

Я не знаю, как написать условие if, я пробовал это {% if post.entity in likes %}, но это не работает. Любая помощь будет очень признательна, я немного застрял

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

Тогда объекты Post будут иметь дополнительный атрибут .is_liked, который будет True, если этот Post нравится вошедшему пользователю.


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 calling reverse(…) [Django] and then wrap it in a HttpResponseRedirect object [Django-doc]. The redirect(…) 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 the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.


Note: Django's DateTimeField [Django-doc] has a auto_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 in ModelForms by default.

Мне кажется, проще выполнить логику сортировки Entities/Likes/User внутри представления и затем передать правильно отформатированные данные в шаблон.

Это хорошая практика, потому что вскоре вы захотите выполнить более сложные преобразования данных, которые будет очень трудно, если вообще возможно, выполнить в шаблоне django. Именно поэтому подобная логика должна находиться внутри представления.

Надеюсь, это вам поможет!

Вернуться на верх