Поставить DISLIKE, удаляя LIKE. Django

Возможно кто-нибудь сможет помочь. Имеется проект на Django, в который я пытаюсь добавить функцию LIKE/DISLIKE. Как пользователю добавить или снять LIKE/DISLIKE я разобрался. Но моя логика имеет пробел, в том что пользователь может поставить и LIKE и DISLIKE (это не совсем правильно). Поэтому я хочу сделать "финт ушами" следующим образом: если пользователь поставил LIKE, потом передумал и ставит DISLIKE, то что бы DISLIKE приплюсовался, а LIKE отминусовался автоматически (так же как происходит на YouTube).

У меня есть следующие вьюхи:

  1. class AddLikeView(View)
  2. class RemoveLikeView(View)
  3. class AddDisLikeView(View)
  4. class RemoveDisLikeView(View)

Я так понимаю, мне надо прописать какую то логику в AddDisLikeView и RemoveLikeView. Подскажите пожалуйста.

class AddDisLikeView(View):
def post(self, request, *args, **kwargs):
    blog_post_id = int(request.POST.get('blog_post_id'))
    user_id = int(request.POST.get('user_id'))
    url_from = request.POST.get('url_from')

    user_inst = User.objects.get(id=user_id)
    blog_post_inst = News.objects.get(id=blog_post_id)

    try:
        blog_dislike_inst = BlogDisLikes.objects.get(blog_post=blog_post_inst, liked_by=user_inst)
    except Exception as e:
        blog_dislike = BlogDisLikes(blog_post=blog_post_inst,
                              disliked_by=user_inst,
                              dislike=True)
        blog_dislike.save()
    return redirect(url_from)


class RemoveLikeView(View):
def post(self, request, *args, **kwargs):
    blog_likes_id = int(request.POST.get('blog_likes_id'))
    url_from = request.POST.get('url_from')

    blog_like = BlogLikes.objects.get(id=blog_likes_id)
    blog_like.delete()
    return redirect(url_from)

Ответы (1 шт):

Автор решения: Andrey Maslov

Вынеси функционал по увеличению, уменьшению лайков и дизлайков в сервисные методы и вызывай их из своих view

например:

def add_dislike(post, user):
    try:
        BlogDisLikes.objects.get(blog_post=post, liked_by=user)
    except BlogDisLikes.DoesNotExist:
        BlogDisLikes.objects.create(blog_post=post, liked_by=user)

        
def remove_dislike(post, user):
    BlogDisLikes.objects.filter(blog_post=post, liked_by=user).delete()
    
    
def add_like(post, user):
    try:
        BlogLikes.objects.get(blog_post=post, liked_by=user)
    except BlogLikes.DoesNotExist:
        BlogLikes.objects.create(blog_post=post, liked_by=user)

        
def remove_like(post, user):
    BlogLikes.objects.filter(blog_post=post, liked_by=user).delete()

    

и тогда твои view будут выглядеть как-то так

class AddDisLikeView(View):
    def post(self, request, *args, **kwargs):
        blog_post_id = int(request.POST.get('blog_post_id'))
        user_id = int(request.POST.get('user_id'))
        url_from = request.POST.get('url_from')

        user_inst = User.objects.get(id=user_id)
        blog_post_inst = News.objects.get(id=blog_post_id)
        remove_like(post=blog_post_inst, user=user_inst)
        add_dislike(post=blog_post_inst, user=user_inst)
        return redirect(url_from)

если ты сделаешь у модели BlogDisLikes уникальный ключ blog_post, liked_by тогда можно просто пытаться сразу создать дизлайк, отлавливая исключение

from django.db import IntegrityError


def add_dislike(post, user):
    try:
        BlogDisLikes.objects.create(blog_post=post, liked_by=user)
    except IntegrityError:
        pass  # ничего не делаем, если такой диздайк уже есть
        

аналогично и для модели лайков

→ Ссылка