Django Conditional ORM Query
Я создаю сайт-блог, где для каждого блога пользователь может поставить лайк или не поставить лайк.
Теперь каждый раз, когда пользователь переходит на страницу Index, я хочу изменить кнопку like, т.е. если пользователю понравился пост, то кнопка dislike, иначе кнопка like.
Для этого мне нужно получить переменную IsLiked из файла views.py.
Вот запрос, который я написал.
posts = Post.objects.exclude(users=request.user).select_related('user__people','ProductAvailability').prefetch_related('images_set').annotate(comments_Count = Count('comments_post',distinct=True)).annotate(Count('Likes',distinct=True)).all().order_by('-id')
for post in posts:
if(post.Likes.filter(id=user_id).exists()):
isLiked = True
else:
isLiked = False
Здесь проблема в том, что для каждого поста отправляется отдельный запрос в БД.
Это модель моего блога ->
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.PROTECT)
# category = models.ForeignKey(Category, on_delete=models.PROTECT)
ProductAvailability = models.ForeignKey(ProductAvailability, on_delete=models.PROTECT, null=True, blank=True)
title = models.CharField(max_length=255,null=True)
description = models.CharField(max_length=1000,null=True)
Likes = models.ManyToManyField(to=User, related_name='Post_likes')
favourites = models.ManyToManyField(to=User,blank=True,related_name="favourite")
Tag1 = models.CharField(max_length=255,null=True,blank=True)
Tag2 = models.CharField(max_length=255,null=True,blank=True)
Tag3 = models.CharField(max_length = 255, null = True, blank = True)
Tag1_Name = models.CharField(max_length=255,null=True,blank=True)
Tag2_Name = models.CharField(max_length=255,null=True,blank=True)
Tag3_Name = models.CharField(max_length=255,null=True,blank=True)
users = models.ManyToManyField(User, related_name='users_hidden_from_post')
Created_date = models.DateTimeField(auto_now_add=True)
Updated_date = models.DateTimeField(auto_now=True)
PS: Пожалуйста, игнорируйте избыточную информацию в модели поста
Я хочу отправить идентификатор пользователя с запросом и проверить, нравится ли отдельное сообщение пользователю или нет.
Вы можете аннотировать Posts условием is_liked, которое проверяет, появляется ли такой User в сквозной модели подобных Post с Exists подзапросом [Django-doc]:
from django.db.models import Exists, OuterRef
posts = Post.objects.exclude(
users=request.user
).select_related(
'user__people', 'ProductAvailability'
).prefetch_related(
'images_set'
).annotate(
comments_Count = Count('comments_post',distinct=True),
Count('Likes',distinct=True),
is_liked=Exists(
Post.Likes.through.objects.filter(
post_id=OuterRef('pk'), user_id=user_id
)
)
).order_by('-id')
Объекты Post, возникающие из этого кверисета, будут иметь дополнительный атрибут .is_liked, который будет True, если user_id появится в Likes для этого Post.
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 theUsermodel [Django-doc] directly. For more information you can see the referencing theUsermodel section of the documentation.
Примечание: обычно имена полей в модели Django записываются в snake_case, а не PascalCase, поэтому должно быть:
likesвместо.Likes