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 && 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) && !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>
视图.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 装饰器功能,但仍然无法解决问题。
我使用的方法在 partial-comment-html 的 script 标签中可用。我怎么解决这个问题。正如我所说,当我按下加载更多按钮时,响应评论所需的表单字段就在这些评论下方,当使用 ajax 加载更多时,这些表单字段中的 csrf_token 信息被删除,新评论中没有任何反应。
注2:输入{{csrf_token}}时,我自己用javascript添加了隐藏的输入字段,但Django意识到我添加了它并阻止了我。
解决方案
推荐阅读
- python-3.x - 有没有办法在张量流中施加约束,我可以在此过程中强制执行一些规则吗?
- sql-server - 无法从同一主机上的 Web 应用程序 docker 访问 docker 托管的 SQL 服务器
- android - Android 密码接收器停止工作?
- python - plt.pcolormesh() 函数如何在 python 中工作
- robotframework - Robot Framework ImapLibrary 删除所有电子邮件不工作
- c# - 工厂模式的含义
- ios - 活动指示器动态改变颜色ios swift
- android - webview 视频事件“onShowCustomView”正在全屏触发,但是当我返回小屏幕时,没有监听器工作
- rsync - Rsync 排除正确的语法
- laravel - Eloquent 的 "with" 不会为一种关系返回任何东西,但会为另一种关系返回任何东西