好的,这已经解决了。只需编辑,以防任何人遇到同样的问题。
在同一个javascript文件中添加标记为答案的评论中发布的代码。 定义时
Wrapper
就是这样。
所以我在通过dropzone.js向django.Django提交POST请求时获得403 Forbidden显示消息说我没有包含CSRF令牌,但我不知道如果我不使用HTML中的表单。
var myDropzone = new Dropzone(...
...//More stuff here
headers:{
'X-CSRFToken' : csrftoken
}
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}Add files{% endblock %}
{% block files %}
<div class="container-fluid" id="container-dropzone">
<div id="actions" class="row">
<div class="col-lg-7">
<span class="btn btn-success file-input-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
</span>
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel upload</span>
</button>
</div>
<div class="col-lg-5">
<!-- file processing state -->
<span class="fileupload-process">
<div id="total-progress" class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress></div>
</div>
</span>
</div>
</div>
<div class="table table-striped files" id="previews">
<div id="template" class="file-row">
<div>
<span class="preview"><img data-dz-thumbnail></span>
</div>
<div>
<p class="name" data-dz-name></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
<div>
<p class="size" data-dz-size></p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0"
aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%"
data-dz-uploadprogress>
</div>
</div>
</div>
<div>
<button class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
<button data-dz-remove class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
<button data-dz-remove class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
</div>
</div> <!-- /table-striped -->
</div> <!-- /container-fluid -->
</div>
{% endblock %}
{% block dz-add %}
<script src="{% static 'js/dropzone-bootstrap.js' %}"></script>
{% endblock %}
在我的 base.html 中添加所有必需的文件(dropzone,jquery,bootstrap和我的自定义javascript文件)
对于django表单处理:
$(function() {
var previewNode = document.querySelector("#template");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
var myDropzone = new Dropzone(document.querySelector("#container-dropzone") , {
url: "/dashby/files/add/", //url to make the request to.
thumbnailWidth: 80,
thumbnailHeight: 80,
parallelUploads: 20,
previewTemplate: previewTemplate,
autoQueue: false,
previewsContainer: "#previews",
clickable: ".file-input-button",
headers: { // Tried to apply the token this way but no success.
'X-CSRFToken': $('meta[name="token"]').attr('content')
}
});
myDropzone.on("addedfile", function(file){
file.previewElement.querySelector(".start").onclick = function(){
myDropzone.enqueueFile(file);
};
});
myDropzone.on("totaluploadprogress", function(progress){
document.querySelector("#total-progress .progress-bar").style.width = progress + "%";
});
myDropzone.on("sending", function(file){
// Show total progress on start and disable START button.
document.querySelector("#total-progress").style.opacity = "1";
file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
});
// Hide progress bar when complete.
myDropzone.on("queuecomplete", function(progress){
document.querySelector("#total-progress").style.opacity = "0";
});
// Setup buttons for every file.
document.querySelector("#actions .start").onclick = function(){
myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
};
document.querySelector("#actions .cancel").onclick = function(){
myDropzone.removeAllFiles(true);
};
});
class DocumentCreate(CreateView):
model = Document
fields = ['file']
def form_valid(self, form):
self.object = form.save()
data = {'status': 'success'}
response = JSONResponse(data, mimetype =
response_mimetype(self.request))
return response
我创建了一个Json响应来处理dropzone。
class Document(models.Model):
file = models.FileField(upload_to = 'files/',
validators=[validate_file_type])
uploaded_at = models.DateTimeField(auto_now_add = True)
extension = models.CharField(max_length = 30, blank = True)
thumbnail = models.ImageField(blank = True, null = True)
def clean(self):
self.file.seek(0)
self.extension = self.file.name.split('/')[-1].split('.')[-1]
if self.extension == 'xlsx' or self.extension == 'xls':
self.thumbnail = 'xlsx.png'
elif self.extension == 'pptx' or self.extension == 'ppt':
self.thumbnail = 'pptx.png'
elif self.extension == 'docx' or self.extension == 'doc':
self.thumbnail = 'docx.png'
def delete(self, *args, **kwargs):
#delete file from /media/files
self.file.delete(save = False)
#call parent delete method.
super().delete(*args, **kwargs)
#Redirect to file list page.
def get_absolute_url(self):
return reverse('dashby-files:files')
def __str__(self):
#cut the 'files/'
return self.file.name.split('/')[-1]
class Meta():
#order by upload_date descending
#for bootstrap grid system. (start left side)
ordering = ['-uploaded_at']
我一直坚持这个问题一天,所以决定在这里寻求帮助,因为我找不到一个。
感谢任何花时间阅读的人以及我能得到的任何帮助/提示。
答案 0 :(得分:2)
只需将{% csrf_token %}
放在Html文件中的任何位置即可。它会自动添加
<input type="hidden" name="csrfmiddlewaretoken" value="**************" />
在向服务器发送数据之前,只需添加额外字段csrf_token
,其值为$("input[name='csrfmiddlewaretoken']").val();
答案 1 :(得分:1)
虽然这是一个旧线程,但我想我应该分享对我有用的解决方案。
var myDropzone = $("#file-upload").dropzone({
url: "/dashboard/api/v1/upload/",
// addRemoveLinks : true,
maxFilesize: 5,
dictResponseError: 'Error uploading file!',
headers: {'X-CSRFToken': window.CSRF_TOKEN},
success: (file, response) => {
console.log(JSON.parse(file.xhr.response));
}
});
答案 2 :(得分:0)
docs建议从cookie中获取CSRF令牌,而不是DOM。试试吧。
答案 3 :(得分:0)
Django的文档有reference for this:
虽然[特殊参数]可用于AJAX POST请求,但它有一些不便之处:您必须记住在每次POST请求时都将CSRF令牌作为POST数据传递。因此,有一种替代方法:在每个
XMLHttpRequest
上,将自定义X-CSRFToken
标头设置为CSRF令牌的值。这通常更容易,因为许多JavaScript框架提供了允许在每个请求上设置标头的钩子 [...]获取令牌非常简单:
// using jQuery 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');
[...] 最后,您必须在AJAX请求中实际设置标头,同时保护CSRF令牌在jQuery 1.5.1及更高版本中使用settings.crossDomain发送到其他域:
function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
如果在开始发出请求之前运行这两个代码块,它应该是Just Work™。
总之,只需使用此代码块:
// from https://docs.djangoproject.com/en/1.10/ref/csrf/ via http://stackoverflow.com/a/39776325/5244995.
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));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
答案 4 :(得分:0)
我刚刚弄清楚了,您要做的就是将其添加到您的dropzone配置中:
headers: {'X-CSRFToken': '{{ csrf_token }}'},
祝你好运!