Невозможно получить идентификатор комментария с помощью AJAX в django
Я бьюсь с этой проблемой уже несколько дней и не могу найти решение для своего случая. Я пытаюсь сделать систему лайков без обновления страницы. В синхронном режиме система лайков и дизлайков работает нормально, но когда я пытаюсь добавить AJAX, я получаю 405 и только один последний комментарий работает на один клик, я понимаю проблему, что Ajax не понимает django urls с id или pk, как в моем варианте {% url 'store:like' comment.pk %} , но как это можно решить?
Вот эта часть из шаблона:
{% for comment in comments %}
<h6 class="card-header">
{{ comment.author }}<small> добавлен {{ comment.created_at|date:'M d, Y H:i' }} </small>
</h6>
<div class="card-body">
<h4>{{ comment }}</h4>
<form id="like" method="POST" data-url="{% url 'store:like' comment.pk %}">
{% csrf_token %}
<input type="hidden" value="{{comment.pk}}" name="id">
<input type="hidden" name="next" value="{{ request.path }}">
<button style="background-color: transparent; border: none; box-shadow: none;" type="submit">
<a class="btn btn-success" id="like"> Likes {{ comment.likes.all.count }}</a>
</button>
</form>
</div>
{% empty %}
<p>Для данного товара ещё нет комментариев.</p>
{% endfor %}
мой вызов ajax в том же шаблоне:
<script type="text/javascript">
$(document).ready(function(){
var endpoint = $("#like").attr("data-url")
$('#like').submit(function(e){
e.preventDefault();
var serializedData = $(this).serialize();
$.ajax({
type: 'POST',
url: endpoint,
data: serializedData,
success: function(response) {
$('#main').load(' #main', function(){
/// can add another function here
});
},
error: function(rs, e) {
alert(rs.responseText);
}
});
})
});
Эта часть из урлов:
path('products/<int:pk>/like/', addlike, name='like'),
Посмотрите для примера:
def addlike(request, *args, **kwargs):
#is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
#if request.method == 'POST' and is_ajax:
pk = request.POST.get('id')
post = Comment.objects.get(pk=pk)
is_dislike = False
for dislike in post.dislikes.all():
if dislike == request.user:
is_dislike = True
break
if is_dislike:
post.dislikes.remove(request.user)
is_like = False
for like in post.likes.all():
if like == request.user:
is_like = True
break
if not is_like:
post.likes.add(request.user)
if is_like:
post.likes.remove(request.user)
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)
#return JsonResponse({"success": True}, status=200)
#else:
#return JsonResponse({"success": False}, status=400)
Как заставить AJAX вызывать в пк то, что мне нужно?
Я думаю, что вы должны отправить csrf_token с ajax запросом, добавьте
headers: { "X-CSRFToken": token }
к вашему ajax запросу, "token - это csrf_token" или добавить @csrf_exempt декоратор к вашей функции, но это сохранит ваше представление небезопасным для CSRF атак.
Вы можете найти больше информации здесь https://docs.djangoproject.com/en/4.0/ref/csrf/
Уберите data-url
и установите атрибут action
, потому что когда вы нажмете кнопку submit, по умолчанию этот POST
запрос будет отправлен на текущий URL и вы получите код состояния 405, но если вы установите action
этот POST
запрос будет отправлен на like
url:
<form id="like" method="POST" action="{% url 'store:like' comment.pk %}">
{% csrf_token %}
<input type="hidden" value="{{comment.pk}}" name="id">
<input type="hidden" name="next" value="{{ request.path }}">
<button style="background-color: transparent; border: none; box-shadow: none;" type="submit">
<a class="btn btn-success" id="like"> Likes {{ comment.likes.all.count }}</a>
</button>
</form>
А в js вы можете получить URL следующим образом
var endpoint = $(this).attr('action');