Djna go проблема с функциональностью поста "лайк" - PullRequest
0 голосов
/ 10 июля 2020

Я создал функцию «лайков» постов на странице списка постов (где отображаются посты одного пользователя). Используя примеры из книги «Django по примерам», я нажимал кнопку ajax лайков под каждым постом. Но работает некорректно. В этом примере кнопка Like была создана для страницы с одним сообщением, и я попытался подогнать ее под страницу со списком сообщений (много сообщений на одной странице). Когда пу sh кнопка лайка в базе данных все нормально - я получил плюс один лайк за конкретный пост. Но во фронтэнде случаются странные вещи - количество лайков для всех постов меняется, как будто все посты связаны. И когда я ставлю лайки и непохожи, количество лайков для всего поста становится очень большим. Я думаю, это происходит, потому что в этом случае Ajax использует один и тот же селектор класса (вместо id) для всех сообщений. Я все еще не очень хорош в Django и Ajax и не могу найти способ заставить это работать правильно. Потрачено много времени на попытки исправить это и поиск в Google безрезультатно. Любая помощь доступна.

Ниже указан код.

Модель сообщения с полями лайков:

class Posts(models.Model):
    author = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True, blank=True)
    content = models.TextField()
    image = models.ImageField(upload_to="posts/%Y/%m/%d", null=True,blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    users_like = models.ManyToManyField(settings.AUTH_USER_MODEL,
                                        related_name='images_liked',
                                        blank=True)
    total_likes = models.PositiveIntegerField(db_index=True,
                                              default=0)

    def __str__(self):
        return self.title

     
    def get_absolute_url(self):
        return reverse("post_detail", kwargs={"slug": self.slug})


def slug_generator(sender, instance, *args, **kwargs):
    if not instance.slug:
        instance.slug = unique_slug_generator(instance)


pre_save.connect(slug_generator, sender=Posts)

Функция post_like в view.py пользователя :

@ajax_required
@login_required
@require_POST
def post_like(request):
    post_id = request.POST.get('id')
    action = request.POST.get('action')
    if post_id and action:
        try:
            post = Posts.objects.get(id=post_id)
            if action == 'like':
                post.users_like.add(request.user)
                create_action(request.user, 'likes', post)
            else:
                post.users_like.remove(request.user)
            return JsonResponse({'status':'ok'})
        except:
            pass
    return JsonResponse({'status':'ok'})

Код в urls.py для этого:

urlpatterns = [
    
    path('like/', views.post_like, name='like'),
...another urls...
]

html для кнопка лайков и подсчет лайков:

{% with total_likes=post.users_like.count users_like=post.users_like.all %}
    <div class="image-info">
      <div>
        <span class="count">
         <span class="total">{{ total_likes }}</span>
         like{{ total_likes|pluralize }}
        </span>
        
        <a href="#" data-id="{{ post.id }}" data-action="{% if request.user in users_like %}un{% endif %}like" class="like button">
          {% if request.user not in users_like %}
            Like
          {% else %}
            Unlike
          {% endif %}
        </a>
      </div>
      
    </div>
    <div class="image-likes">
     
     
    </div>
  {% endwith %}

И в том же файле html, где находится кнопка, внизу находится ajax код для функции лайков:

{% block domready %}
$('a.like').click(function(e){
    e.preventDefault();
    
    $.post('/like/',
      {
        id: $(this).data('id'),
        action: $(this).data('action')
      },
      function(data){
        if (data['status'] == 'ok')
        {
          var previous_action = $('a.like').data('action');

          // toggle data-action
          $('a.like').data('action', previous_action == 'like' ? 'unlike' : 'like');
          // toggle link text
          $('a.like').text(previous_action == 'like' ? 'Unlike' : 'Like');

          // update total likes
          var previous_likes = parseInt($('span.count .total').text());
          $('span.count .total').text(previous_action == 'like' ? previous_likes + 2 : previous_likes - 2);
          
        }
      }
    );
    
  });
{% endblock %}

1 Ответ

1 голос
/ 10 июля 2020

Вы захотите изменить только нажатую кнопку Like, поместив ее в свою click функцию. Вы можете немного привести свой код в порядок, но чтобы он оставался похожим, вы можете сделать что-то вроде:

$('a.like').click(function(e){
    e.preventDefault();
    // Get the clicked button.
    const $clickedButton = $( this );
    
    $.post('/like/',
        {
            id: $clickedButton.data('id'),
            action: $clickedButton.data('action')
        }, 
        function(data) {
            if (data['status'] == 'ok') {
                // Update the clicked button only.
                var previous_action = $clickedButton.data('action');
                
                // toggle data-action
                $clickedButton.data('action', previous_action == 'like' ? 'unlike' : 'like');
                // toggle link text
                $clickedButton.text(previous_action == 'like' ? 'Unlike' : 'Like');

                // update total likes
                const $total = $clickedButton.prev('span.count').children('.total');
                var previous_likes = parseInt($total.text());
                $total.text(previous_action == 'like' ? previous_likes + 2 : previous_likes - 2);
            }
        }
    );
});

Я не уверен на 100%, почему вы добавляете / вычитаете 2 из общего количества, а не 1 , но мне не хватает контекста.

...