Django, Ajax, csrftoken. Please tell me what is the problem.

huangapple go评论72阅读模式
英文:

Django, Ajax, csrftoken. Please tell me what is the problem

问题

以下是代码的翻译部分:

UserWarning: 模板中使用了{% csrf_token %},但上下文未提供该值。通常是因为未使用RequestContext。
这通常是由于未使用RequestContext导致的。

在HTML模板中一切正常。切换到AJAX后,出现了这个错误。
在HTML模板中一切正常,但切换到AJAX后出现了这个错误。

尝试了以下提示,但没有帮助:
尝试了以下提示,但没有帮助:

addnew.html

{% load widget_tweaks %}

<form method="post" action="{% url 'table:addnew' %}" class="js-product-add-form">
    {% csrf_token %}
    <div class="modal-header">
        <h5 class="modal-title modalLabel">添加记录</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
    </div>
    <div class="modal-body">
        {% for field in form %}
        <div class="form-group{% if field.errors %} has-error{% endif %}">
            <label for="{{ field.id_for_label }}">{{ field.label }}</label>
            {% render_field field class="form-control" %}
            {% for error in field.errors %}
            <p class="help-block">{{ error }}</p>
            {% endfor %}
        </div>
        {% endfor %}
        <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
            <input type="submit" class="btn btn-primary" value="添加" />
        </div>
    </div>
</form>

views.py

def index(request):
    snj = ScheduleNotJob.objects.all()
    form = SNJ()
    return render(request, "index.html", {'snj': snj, 'form': form})

def save_product_form(request, form, template_name):
    data = dict()
    if request.method == 'POST':
        if form.is_valid():
            form.save()
            data['form_is_valid'] = True
            SNJ = ScheduleNotJob.objects.all()
            data['html_product_list'] = render_to_string('table.html', {
                'snj': SNJ
            })
        else:
            data['form_is_valid'] = False
    context = {'form': form}
    data['html_form'] = render_to_string(template_name, context, request=request)
    return JsonResponse(data)

def addnew(request):
    if request.method == 'POST':
        form = SNJ(request.POST)
    else:
        form = SNJ()
    return save_product_form(request, form, 'addnew.html')

def edit(request, id):
    elem = ScheduleNotJob.objects.get(id=id)
    if request.method == "POST":
        form = SNJ(request.POST, instance=elem)
    else:
        form = SNJ(instance=elem)
    return save_product_form(request, form, 'edit.html')

def destroy(request, id):
    snj = ScheduleNotJob.objects.get(id=id)
    snj.delete()
    return HttpResponseRedirect(reverse('table:index'))

addnew.html

$(document).ready(function(){
    var loadForm = function () { 
        var btn = $(this);
        $.ajax({
            url: btn.attr("data-url"),
            type: 'get',
            dataType: 'json',
            beforeSend: function () {
                $("#modal-product .modal-content").html("");
                $("#modal-product").modal("show");
            },
            success: function (data) {
                $("#modal-product .modal-content").html(data.html_form);
            },
        });
    };
    
    var saveForm = function () {
        var form = $(this);
        $.ajax({
            url: form.attr("action"),
            data: form.serialize(),
            type: form.attr("method"),
            dataType: 'json',
            success: function (data) {
                if (data.form_is_valid) {
                    $("#bootstrapdatatable tbody").html(data.html_product_list);
                    $("#modal-product").modal("hide");
                    table.draw();
                }
                else {
                    $("#modal-product .modal-content").html(data.html_form);
                }
            }
        });
        return false;
    };

    // 添加产品
    $(".addSpan").on("click", loadForm);
    $("#modal-product").on("submit", ".js-product-update-form", saveForm);

    // 更新产品
    $("#bootstrapdatatable").on("click", ".editSpan", loadForm);
    $("#modal-product").on("submit", ".js-product-add-form", saveForm);
});
英文:

UserWarning: A {% csrf_token %} was used in a template, but the context did not provide the value. This is usually caused by not using RequestContext.
warnings.warn(

On HTML templates everything worked. After switching to AJAX, this error appeared
Tried these tips, did not help: https://stackoverflow.com/questions/65485435/how-can-i-send-a-csrf-token-in-a-form. https://django.readthedocs.io/en/latest/howto/csrf.html.
addnew.html

{% load widget_tweaks %}
&lt;form method=&quot;post&quot; action=&quot;{% url &#39;table:addnew&#39; %}&quot; class=&quot;js-product-add-form&quot;&gt;  
{% csrf_token %}
&lt;div class=&quot;modal-header&quot;&gt;
&lt;h5 class=&quot;modal-title modalLabel&quot;&gt;Добавить запись&lt;/h5&gt;
&lt;button type=&quot;button&quot; class=&quot;btn-close&quot; data-bs-dismiss=&quot;modal&quot; aria-label=&quot;Close&quot;&gt;&lt;/button&gt;
&lt;/div&gt;
&lt;div class=&quot;modal-body&quot;&gt; 
{% for field in form %}
&lt;div class=&quot;form-group{% if field.errors %} has-error{% endif %}&quot;&gt;
&lt;label for=&quot;{{ field.id_for_label }}&quot;&gt;{{ field.label }}&lt;/label&gt;
{% render_field field class=&quot;form-control&quot; %}
{% for error in field.errors %}
&lt;p class=&quot;help-block&quot;&gt;{{ error }}&lt;/p&gt;
{% endfor %}
&lt;/div&gt;
{% endfor %}
&lt;div class=&quot;modal-footer&quot;&gt;
&lt;button type=&quot;button&quot; class=&quot;btn btn-secondary&quot; data-bs-dismiss=&quot;modal&quot;&gt;Отмена&lt;/button&gt;
&lt;input type=&quot;submit&quot; class=&quot;btn btn-primary&quot; value=&quot;Добавить&quot; /&gt;
&lt;/div&gt; 
&lt;/div&gt; 
&lt;/form&gt;  

views.py

def index(request):  
snj = ScheduleNotJob.objects.all()  
form = SNJ()   
return render(request,&quot;index.html&quot;,{&#39;snj&#39;: snj, &#39;form&#39;:form})  
def save_product_form(request, form, template_name):
data = dict()
if request.method == &#39;POST&#39;:  
if form.is_valid():
form.save()
data[&#39;form_is_valid&#39;] = True
SNJ = ScheduleNotJob.objects.all()
data[&#39;html_product_list&#39;] = render_to_string(&#39;table.html&#39;, {
&#39;snj&#39;: SNJ
})
else:
data[&#39;form_is_valid&#39;] = False
context = {&#39;form&#39;: form}
data[&#39;html_form&#39;] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
def addnew(request):
if request.method == &#39;POST&#39;:
form = SNJ(request.POST)
else:
form = SNJ()
return save_product_form(request, form, &#39;addnew.html&#39;)  
def edit(request, id):
elem = ScheduleNotJob.objects.get(id=id)
if request.method == &quot;POST&quot;:
form = SNJ(request.POST, instance=elem)  
else:  
form = SNJ(instance=elem)
return save_product_form(request, form, &#39;edit.html&#39;)
def destroy(request, id):  
snj = ScheduleNotJob.objects.get(id=id)  
snj.delete()  
return HttpResponseRedirect(reverse(&#39;table:index&#39;)) 

addnew.html

$(document).ready(function(){
var loadForm = function () { 
var btn = $(this);
$.ajax({
url: btn.attr(&quot;data-url&quot;),
type: &#39;get&#39;,
dataType: &#39;json&#39;,
beforeSend: function () {
$(&quot;#modal-product .modal-content&quot;).html(&quot;&quot;);
$(&quot;#modal-product&quot;).modal(&quot;show&quot;);
},
success: function (data) {
$(&quot;#modal-product .modal-content&quot;).html(data.html_form);
},
});
};
var saveForm = function () {
var form = $(this);
$.ajax({
url: form.attr(&quot;action&quot;),
data: form.serialize(),
type: form.attr(&quot;method&quot;),
dataType: &#39;json&#39;,
success: function (data) {
if (data.form_is_valid) {
$(&quot;#bootstrapdatatable tbody&quot;).html(data.html_product_list);
$(&quot;#modal-product&quot;).modal(&quot;hide&quot;);
table.draw();
}
else {
$(&quot;#modal-product .modal-content&quot;).html(data.html_form);
}
}
});
return false;
};
// Add product
$(&quot;.addSpan&quot;).on(&quot;click&quot;, loadForm);
$(&quot;#modal-product&quot;).on(&quot;submit&quot;, &quot;.js-product-update-form&quot;, saveForm);
// Update product
$(&quot;#bootstrapdatatable&quot;).on(&quot;click&quot;, &quot;.editSpan&quot;, loadForm);
$(&quot;#modal-product&quot;).on(&quot;submit&quot;, &quot;.js-product-add-form&quot;, saveForm);
});

答案1

得分: 0

在没有RequestContext的情况下,你的HTML页面被渲染如下:

return render_to_response('yourpage.html', context_instance=RequestContext(request))

在渲染HTML页面的位置,将此渲染添加到你的views.py中。

英文:

Your html page is rendered without RequestContext so:

return render_to_response(&#39;yourpage.html&#39;, context_instance=RequestContext(request))

add this render to your views.py where you render the html page.

答案2

得分: 0

为了修复我在评论中提到的错误,你可以按照以下方式在你的AJAX请求标头中包含CSRF令牌:

var csrftoken = $("[name=csrfmiddlewaretoken]").val(); // 从表单获取CSRF令牌值
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        xhr.setRequestHeader("X-CSRFToken", csrftoken); // 在请求标头中包含CSRF令牌
    }
});

同时,你需要修改你的视图,需要将render_to_string替换为render,这样我们才能使用CSRF令牌上下文处理器渲染模板。

新的视图将如下所示:

def save_product_form(request, form, template_name):
    data = dict()
    if request.method == 'POST':  
        if form.is valid():
            form.save()
            data['form_is_valid'] = True
            SNJ = ScheduleNotJob.objects.all()
            data['html_product_list'] = render_to_string('table.html', {
                'snj': SNJ
            })
        else:
            data['form_is_valid'] = False
    context = {'form': form}
    data['html_form'] = render(request, template_name, context)
    return JsonResponse(data)

抱歉回复晚了,我现在看到你的消息了。如果这对你有用,请给我点赞,如果有任何问题,请留言,我会尽力解决。

英文:

To fix this error as I mentioned in the comment, you can include the CSRF token in your AJAX request headers as follows

var csrftoken = $(&quot;[name=csrfmiddlewaretoken]&quot;).val(); // get the CSRF 
token value from the form
$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader(&quot;X-CSRFToken&quot;, csrftoken); // include the CSRF token in the request headers
}

});

and also you need to modify your view, you need to replace the render_to_string to render then only we can render the template with the CSRF token context processor

the new view will be like follows

def save_product_form(request, form, template_name):
data = dict()
if request.method == &#39;POST&#39;:  
if form.is_valid():
form.save()
data[&#39;form_is_valid&#39;] = True
SNJ = ScheduleNotJob.objects.all()
data[&#39;html_product_list&#39;] = render_to_string(&#39;table.html&#39;, {
&#39;snj&#39;: SNJ
})
else:
data[&#39;form_is_valid&#39;] = False
context = {&#39;form&#39;: form}
data[&#39;html_form&#39;] = render(request,template_name, context)
return JsonResponse(data)

sorry for the late response I saw your message now. Try this and give me an upvote if it works for you if you have any issue just comment I'll try to figure out

huangapple
  • 本文由 发表于 2023年3月1日 09:24:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75598802.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定