Показать больше комментариев, используя ajax с Django

#python-3.x #django #ajax

#python-3.x #django #ajax

Вопрос:

С помощью Django я сделал кнопку Показать больше комментариев с помощью ajax. Эта система работает, но проблема в том, что в комментариях, которые я привел таким образом, есть поля формы, и когда я нажимаю кнопку «Еще», csrf_token не отображается в этом поле комментариев. Таким образом, я получаю ошибку csrf_token при отправке формы. Я оставляю свои коды ниже.

Чтобы решить эту проблему, я запустил форму с помощью метода get, но как таковая функция в представлениях направляет меня на страницу с помощью JsonResponse. Другим решением было предоставить информацию заголовка csrf_token, но это также не решило проблему.

blog_detail.html

 <script>
$(document).ready(function(){
  $('#load_form').submit(function(e){
    e.preventDefault();
    var limit = $(this).attr('limit')
    var page = document.getElementById('pagination')
    var blog_comment_list = $('#blog-comment-list')
    var serializedData = $(this).serialize();
    $.ajax({
      type:'GET',
      url: "{% url 'load-more-comments' %}",
      data : serializedData,
      success: function(response){
        blog_comment_list.html(response.comment_html)
        if (page.value >= limit){
          $('#submit_button').hide()
        }
        page.value = parseInt(page.value) 1
      },
    })
  })
})

</script>

<div id="blog-comment-list">
  {% include 'front_end/blog/comment/partial-comment.html' %}
</div>
 <form method="GET" id="load_form" limit="{{num_pages}}">
 <input type="hidden" name="pk" value="{{details.id}}">
 <input type="hidden" name="page" value="2" id="pagination">
 <input type="submit" name="load" value="Load More" id="submit_button">
 </form>
 

частичный комментарий-html

 <div class="media-holder mt-5">
  <h3 class="title mb-3">All Comments</h3>
  {% for item in comments %}
  <div class="infinite-container">
  <div class="media mb-5">
    <img class="img-fluid rounded-circle box-shadow mr-4" alt="image" src="{{item.owner.get_image_or_default}}" style="width: 100px;height: 100px;">
    <div class="media-body">
      <h6>{{item.owner.name}}  {{item.owner.surname}}</h6> 
      <br>
      <small><span style="font-size:14px;" class="stars-container stars-{% widthratio item.rate.rate 1 20 %}" id="stars">★★★★★</span></small>
      <div class="comment-date"> <span class="date">{{item.created_date|naturaltime}}</span>
      </div>
      <p>{{item.content}} </p>
      
      <div align="center">
        <a href="javascript:void(0)" class="show-answers" id="comment-id-{{item.id}}">{% if item.comments.all %}Cevapları Görüntüle ({{item.comments.count}}){% else %}Cevap Ver{% endif %}</a>
      </div>
      
      <div class="generic-comment" id="generic-comment-id-{{item.id}}" style="display:none;">
        <!-- -->
        <div class="infinite-generic-comment">
        <form action="{% url 'comment-answer' %}" method="POST" id="answer_form">
        {% csrf_token %}
        <input type="hidden" name="comment_id" value="{{item.id}}">
          <div class="row">
            <div class="col-9">
              <input type="text" placeholder="Cevap Ver" name='generic_comment' class="form-control">
            </div>
            <div class="col-2">
              <input type="submit" value="Cevap Ver" class="btn btn-outline-primary">
            </div>
           </div>
          </form>
          {% for comment in item.comments.all %}
          <div class="media mb-2">
            <img class="img-fluid rounded-circle box-shadow mr-4" alt="image" src="{{item.owner.get_image_or_default}}" style="width: 100px;height: 100px;">
            <div class="media-body">
              <h6>{{comment.owner.name}}  {{comment.owner.surname}}</h6> 
              <div class="comment-date"> <span class="date">{{comment.created_date|naturaltime}}</span>
              </div>
              <p>{{comment.content}} </p>
            </div>
          </div>
          {% endfor %}
        </div>
        <!-- -->
      </div>
    </div>
    
  </div>

</div>
{% endfor %}
</div>
<script>
 
var aTag = document.getElementsByClassName('show-answers')
for (let i = 0; i< aTag.length; i  ){
  aTag[i].addEventListener('click', (event) => {

    var generic = document.getElementById(`generic-${event.target.id}`)
    if (generic.style.display == 'none'){
      $(`#generic-${event.target.id}`).slideDown('slow')
    }
    else{
      $(`#generic-${event.target.id}`).slideUp('slow')
    }
  })
}

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie amp;amp; document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i  ) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length   1) === (name   '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length   1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}


$(document).ready(function(){
  $('#answer_form').submit(function(e){
    e.preventDefault()
    var serializedData = $(this).serialize()
    var url = $(this).attr('action')

    $.ajaxSetup({
      beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) amp;amp; !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
          }
        },
        //headers: { "X-CSRFToken": getCookie("csrftoken") }
    });
    $.ajax({
      type:'POST',
      url: url,
      data:serializedData,
      success: function(response){
        if (response.success){
          $('#answer_form').trigger('reset')
          Swal.fire(
          'Başarılı!',
          'Cevap onaya gönderildi',
          'success'
          )
        }
      }
    })
  })
})
</script>
 

views.py

 def answer_comment(request):
    if request.method=='POST':
        comment = Comment.objects.get(id=request.POST.get('comment_id'))
        comment.comments.create(owner=request.user, content=request.POST.get('generic_comment'))
        return JsonResponse({'success':True},status=200)
    return JsonResponse({'success':False}, status = 403)
 

Примечание: я попробовал функцию декоратора csrf_exempt, но все равно не смог решить проблему.

Методы, которые я использую, доступны в теге script в partial-comment-html. Как я могу решить эту проблему. Как я уже сказал, когда я нажимаю кнопку загрузить больше, необходимые поля формы для ответа на комментарий находятся чуть ниже этих комментариев, а при загрузке больше с помощью ajax информация csrf_token удаляется в этих полях формы, и в новых комментариях ничего не происходит.

Примечание 2: при вводе {{csrf_token}} я сам добавил скрытое поле ввода с помощью javascript, но Django понял, что я его добавил, и помешал мне.

Комментарии:

1. что вы подразумеваете под «но Django понял, что я добавил это и помешал мне»? вы когда-нибудь входили serializedData в систему, чтобы просмотреть данные? является ли токен csrf там пустым? Я не использую jquery, но с ванильным запросом XHR i.setRequestHeader("X-CSRFToken", "{{ csrf_token }}") отлично работает в аналогичной настройке.

2. $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) amp;amp; !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } }, //headers: { "X-CSRFToken": getCookie("csrftoken") } }); Да, я использовал эту структуру, я попробовал часть в строке комментария и ту часть, которой нет, но проблема {{csrf_token}} в том, что в моей форме нет элемента.