Как я могу подключить кнопку Django как Ajax для автоматического обновления - PullRequest
0 голосов
/ 24 июня 2019

У меня есть проект Django, над которым я работаю. Пользователи смогут любить и не нравиться сообщение.

models.py

class Tweet(models.Model):
    tweet_user = models.ForeignKey(User, on_delete=models.CASCADE)
    tweet_message = models.TextField()
    tweet_date = models.DateTimeField(auto_now_add=True)
    tweet_like_counter = models.IntegerField(default=0)
    tweet_picture = models.FileField(null=True,blank=True)
    def __str__(self):
        return self.tweet_message


class Like(models.Model):
    user = models.ManyToManyField(User)
    tweet = models.ForeignKey(Tweet, on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return self.tweet.tweet_message

class Disike(models.Model):
    user = models.ManyToManyField(User)
    tweet = models.ForeignKey(Tweet, on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return self.tweet.tweet_message

views.py

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
@login_required
def like(request, pk):
    currentTweet = get_object_or_404(Tweet,pk=pk)
    username = User.objects.get(pk=request.user.id)
    like_queryset = Like.objects.filter(tweet=currentTweet, user=username)
    dislike_queryset = Disike.objects.filter(tweet=currentTweet, user=username)


    if like_queryset.exists():
        Like.objects.filter(tweet=currentTweet, user=username).delete()
        dislikeobject = Disike.objects.filter(tweet=currentTweet).count()
        likeobject = Like.objects.filter(tweet=currentTweet).count()
        currentTweet.tweet_like_counter = likeobject - dislikeobject
        currentTweet.save()

    if dislike_queryset.exists():
        Disike.objects.filter(tweet=currentTweet, user=username).delete()
        dislikeobject = Disike.objects.filter(tweet=currentTweet).count()
        likeobject = Like.objects.filter(tweet=currentTweet).count()
        currentTweet.tweet_like_counter = likeobject - dislikeobject
        currentTweet.save()


    like = Like.objects.create(tweet=currentTweet)
    like.user.add(username)
    dislikeobject = Disike.objects.filter(tweet=currentTweet).count()
    likeobject = Like.objects.filter(tweet=currentTweet).count()
    currentTweet.tweet_like_counter = likeobject - dislikeobject
    currentTweet.save()

    return JsonResponse({
        'like_counter': currentTweet.tweet_like_counter
    })


@csrf_exempt
@login_required
def dislike(request, pk):
    currentTweet = get_object_or_404(Tweet, pk=pk)
    username = User.objects.get(pk=request.user.id)
    like_queryset = Like.objects.filter(tweet=currentTweet, user=username)
    dislike_queryset = Disike.objects.filter(tweet=currentTweet, user=username)

    if dislike_queryset.exists():
        Disike.objects.filter(tweet=currentTweet, user=username).delete()
        dislikeobject = Disike.objects.filter(tweet=currentTweet).count()
        likeobject = Like.objects.filter(tweet=currentTweet).count()
        currentTweet.tweet_like_counter = likeobject - dislikeobject
        currentTweet.save()

    if like_queryset.exists():
        Like.objects.filter(tweet=currentTweet, user=username).delete()
        dislikeobject = Disike.objects.filter(tweet=currentTweet).count()
        likeobject = Like.objects.filter(tweet=currentTweet).count()
        currentTweet.tweet_like_counter = likeobject - dislikeobject
        currentTweet.save()

    dislike = Disike.objects.create(tweet=currentTweet)
    dislike.user.add(username)
    dislikeobject = Disike.objects.filter(tweet=currentTweet).count()
    likeobject = Like.objects.filter(tweet=currentTweet).count()
    currentTweet.tweet_like_counter = likeobject - dislikeobject
    currentTweet.save()

    return JsonResponse({
        'like_counter':  currentTweet.tweet_like_counter

    })

шаблон

 <p class='id{{ post.tweet_user }}' name="tweetlikes" class="card-text" style="background-color: lightgray;"><strong>{{ post.tweet_like_counter }} likes </strong></p>

<form   id="like{{ post.tweet_user }}" method="POST" name="likeform" action="{% url 'like' pk=post.pk %}"   style="float:left;">
          {% csrf_token %}
        <button type="submit" class="like-form" name="like" class="btn btn-primary" >Like</button>
</form>

<script>
       $('#like{{ post.tweet_user }}').on('submit', function(event){
           event.preventDefault();
                             var oldVal =  parseInt($(".id{{ post.tweet_user }}").text())
        var url = $('#like{{ post.tweet_user }}').attr('action');

        $.ajax({
            type: 'POST',
            url:url,
            data:{
                'like_counter':oldVal
            },
            dataType: 'json',
            success:function(data){
                $(".id{{ post.tweet_user }}").html(data.like_counter + " " +  "likes");
            }
        })
    })
</script>

<form   id="dislike{{ post.tweet_user }}" name="dislikeform" method="POST" action="{% url 'dislike' pk=post.pk %}" style="float:right;" >
          {% csrf_token %}
    <button type="submit"  class="btn btn-primary">Dislike</button>
</form>

<script>
   $('#dislike{{ post.tweet_user }}').on('submit', function(e){
           e.preventDefault();
                             var oldVal =  parseInt($(".id{{ post.tweet_user }}").text())
        var url = $('#dislike{{ post.tweet_user }}').attr('action');

        $.ajax({
            type: 'POST',
            url:url,
            data:{
                'like_counter':oldVal
            },
            dataType: 'json',
            success:function(data){
                $(".id{{ post.tweet_user }}").html(data.like_counter + " " +  "likes");
            }
        })
    })
</script>
</div>

Проблема в моем аяксе. Функциональность моего сайта прекрасно работает. Это просто Аякс. Когда пользователь нажимает кнопку «Мне нравится» в первом сообщении, он позволяет пользователю только один раз нажать кнопку «Мне нравится». Когда другой пользователь публикует сообщение (которое создает два сообщения на странице), кнопки «похожие сообщения» больше не работают, и это меняет тег номера «одинаково», а также делает данные разнородными. Помогите пожалуйста?

1 Ответ

0 голосов
/ 24 июня 2019

Почему пользователи связаны с лайками / дислайками с ManyToManyField? Можно ли поделиться одним «лайком» среди пользователей? ForeignKey будет хорошо работать здесь.

Кроме того, поскольку в вашем коде указано, что у пользователя не может быть Like и Dislike в одном и том же «твите» одновременно, я предлагаю вам свернуть эти две модели в одну с Boolean или числовым полем. значение +1 или -1.

Вместо обработки базы данных с таким количеством запросов вы можете использовать [update_or_create][1] и F () или Subquery () выражение или Счет / сумма агрегация , Последний также исправит проблему с условиями гонки в запросах на обновление.

def like(request, pk):
    Like.objects.update_or_create(tweet_id=pk, user=request.user, 
        defaults={"value": <+1/-1>})
    Tweet.objects.filter(pk=pk, ).annotate(likes_count=Sum(tweet__like__value), ).\
        update(tweet_like_counter=F(likes_count), )
    like_counter = Tweet.objects.values_list('tweet_like_counter', flat=True).get(pk=pk,)

    return JsonResponse({
        'like_counter': like_counter
    })

Первый оператор будет создан или обновлен, если существует объект Like с user_id и tweet_id. Обратите внимание, что значение user уже существует в объекте request, поэтому вам не нужно делать дополнительные запросы для его достижения. Также вам не нужно создавать экземпляр Tweet объекта с заданным значением tweet_id (равным pk arg) - здесь достаточно pk / tweer_id.

Следующий оператор обновит tweet_like_counter на основе агрегации всех существующих лайков / дислайков. И это обновление выполняет одну команду SQL вместо 4 команд в вашем коде: получить объект Tweet, получить два счетчика, сохранить объект Tweet с новым счетчиком.

Оператор три извлечет текущий like_counter. Обратите внимание, он выбирает один столбец вместо создания полного Tweet объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...