Проблема с подсчетом в блоге django: использование django ajax - PullRequest
0 голосов
/ 04 мая 2020

Я создал кнопку «Нравится» для своего django блога, используя ajax, но я получаю сообщение об ошибке, что он не считается должным образом, сначала его 0, как в сообщении, когда я нажимаю, как он работает 1, как появился с кнопкой непохожий, но когда я нажимаю непохожий и снова как, он дает 2 лайка, а иногда, когда мне не нравится, он показывает -1, как я думаю, это jQuery проблема. Я не эксперт в jQuery

jQuery

$(document).ready(function() {
  function updateText(btn, newCount, verb) {
      btn.text(newCount + " " + verb)
  }

  $(".like-btn").click(function(e) {
    e.preventDefault()
    var this_ = $(this)
    var likeUrl = this_.attr("data-href")
    var likeCount = parseInt(this_.attr("data-likes")) |0
    var addLike = likeCount + 1
    var removeLike = likeCount - 1
    if (likeUrl){
       $.ajax({
        url: likeUrl,
        method: "GET",
        data: {},
        success: function(data){
          console.log(data)
          var newLikes;
          if (data.liked){
              updateText(this_, addLike, "Unlike")
          } else {
              updateText(this_, removeLike, "Like")
              // remove one like
          }

        }, error: function(error){
          console.log(error)
          console.log("error")
        }
      })
    }
  })
})

post. html

 {% if user not in post.likes.all %}
           <p><a class='like-btn' data-href='{{ object.get_api_like_url }}'
                 data-likes='{{ object.likes.all.count }}' href='{{ object.get_like_url }}'>
               {{ object.likes.all.count }} Like</a></p>
  {% else %}
            <p><a class='like-btn' data-href='{{ object.get_api_like_url }}'
                 data-likes='{{ object.likes.all.count }}' href='{{ object.get_like_url }}'>
                {{ object.likes.all.count }} Unlike</a></p>
  {% endif %}

views.py

class PostLikeToggle(RedirectView):

      def get_redirect_url(self, *args, **kwargs):
      obj = get_object_or_404(Post, pk=kwargs['pk'])
      url_ = obj.get_absolute_url()
      user = self.request.user
      if user.is_authenticated:
         if user in obj.likes.all():
            obj.likes.remove(user)
         else:
            obj.likes.add(user)
      return url_

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions
from django.contrib.auth.models import User

class PostLikeApiToggle(APIView):


    authentication_classes = [authentication.SessionAuthentication]
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request, pk, format=None):

        obj = get_object_or_404(Post, pk=pk)
        url_ = obj.get_absolute_url()
        user = self.request.user
        updated = False
        liked =False
        if user.is_authenticated:
           if user in obj.likes.all():
              liked = False
              obj.likes.remove(user)
           else:
               liked = True
               obj.likes.add(user)
        updated = True
        data = {
               "updated":updated,
                "liked":liked
               }

       return Response(data)

models.py

class Post(models.Model):

     title = models.CharField(max_length=200)
     author = models.ForeignKey(User,on_delete=models.CASCADE)
     likes =models.ManyToManyField(User,blank=True,related_name='post_likes')
     content = models.TextField()
     img = models.ImageField(upload_to='pics',blank=True)
     time = models.DateTimeField(default=timezone.now)

     def __str__(self):
       return self.title

    def get_absolute_url(self):
        return reverse('LoveTravel-Details', kwargs={'pk': self.pk})

    def get_like_url(self):
        return reverse('Like-Toggle', kwargs={'pk':self.pk})

   def get_api_like_url(self):
       return reverse('Like-Api-Toggle', kwargs={'pk':self.pk})

Ответы [ 2 ]

0 голосов
/ 05 мая 2020

Проблема +2 / -1, вероятно, решается с помощью того, что ваш API просто возвращает фактический новый счетчик лайков.

  • Я удалил функцию javascript, включив проверку if(likeUrl) .
  • Переменные addLike / removeLike были заменены свойством data.n_likes.
  • Поскольку это действие изменяет состояние на сервере, лучше отправить его как действие POST чем GET.
function updateText(btn, newCount, verb) {
  btn.text(newCount + " " + verb);
}

$(document).ready(function() {
  $(".like-btn").click(function(e) {
    e.preventDefault();
    var this_ = $(this);
    var likeUrl = this_.attr("data-href");
    if (!likeUrl) return;
    $.ajax({
      url: likeUrl,
      method: "POST",
      data: {},
      success: function(data) {
        console.log(data);
        var newLikes;
        if (data.liked) {
          updateText(this_, data.n_likes, "Unlike");
        } else {
          updateText(this_, data.n_likes, "Like");
        }
      },
      error: function(error) {
        console.log(error);
        console.log("error");
      },
    });
  });
});

и на бэкэнде - вам не нужен DRF для этого, но так как он уже есть -

  • Используйте def post вместо def get
  • Нет необходимости проверять подлинность пользователя; класс разрешений делает это
  • Возвращает одинаковое количество в ответе (и отбрасывает ненужные updated).
class PostLikeApiToggle(APIView):

    authentication_classes = [authentication.SessionAuthentication]
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, pk, format=None):
        obj = get_object_or_404(Post, pk=pk)
        url_ = obj.get_absolute_url()
        user = self.request.user
        liked = False
        if obj.likes.filter(id=user.id).exists():
            obj.likes.remove(user)
        else:
            obj.likes.add(user)
            liked = True

        return Response({
            "liked": liked,
            "n_likes": obj.likes.count(),
        })

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

0 голосов
/ 04 мая 2020

Скорее всего, ваша проблема связана с расой. Это означает, что при двойном нажатии на одну и ту же кнопку ваш код еще не обновил базу данных, чтобы отразить + 1 / -1, поэтому следующий щелчок добавит / удалит дополнительное число.

Есть несколько способов вы можете бороться с этим, например, используя F-выражения или встроенный подсчет JS, но лучшим способом, вероятно, будет просто добавить флаг к вашему JS, чтобы запретить симпатии / неприязнь, пока ваш текущий запрос JS не будет обработан. Это можно легко сделать, отключив кнопки, когда на них уже нажали, а затем включив их снова, когда ответ AJAX завершен (с использованием обратного вызова complete AJAX).

Еще несколько улучшений, которые вы может сделать:

1) Удалите лишнюю if user.is_authenticated (так как похоже, что вы уже определили, что требования в permission_classes

2) Вместо if user in obj.likes.all(): используйте obj.likes.filter(likes=user), и затем реструктурировать условную работу на основе этого

...