2016-09-29 4 views
0

これで解決しました。誰かが同じ問題に遭遇した場合に備えて編集するだけです。csrf_tokenをdropzoneに含めるには投稿要求(Django)

コメントは同じJavaScriptファイルのコメントとして投稿されています。 定義するとき

var myDropzone = new Dropzone(... 
    ...//More stuff here 
    headers:{ 
    'X-CSRFToken' : csrftoken 
    } 

それがそれです。

dropzone.jsからdjango.DjangoにPOSTリクエストを送信するときに403 Forbiddenを取得すると、私がCSRFトークンを含んでいないというメッセージが表示されましたが、実際には使用していない場合HTML内のフォームすべての必要なファイルを追加し、私のbase.htmlイム(ドロップゾーン、jqueryの、ブートストラップと私のカスタムJavaScriptファイルで

document_form.html

{% 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 %} 

ドロップゾーン-bootstrap.js

$(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); 
    }; 
}); 

django形式の処理の場合:

views.py

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 

マイ "ドキュメント" モデル

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'] 

私はドロップゾーンを処理するために、JSONレスポンスを作成しました。私は今、その日のために、この問題で立ち往生してきた

from django.http import HttpResponse 
import json 

MIMEANY = '*/*' 
MIMEJSON = 'application/json' 
MIMETEXT = 'text/plain' 

# Integrating Dropzone.js with Django. 
def response_mimetype(request): 
    can_json = MIMEJSON in request.META['HTTP_ACCEPT'] 
    can_json |= MIMEANY in request.META['HTTP_ACCEPT'] 
    return MIMEJSON if can_json else MIMETEXT 

# Custom HttpResponse 
class JSONResponse(HttpResponse): 
    def __init__(self, obj='', json_opts=None, mimetype=MIMEJSON, 
       *args, **kwargs): 
     json_opts = json_opts if isinstance(json_opts, dict) else {} 
     content = json.dumps(obj, **json_opts) 
     super(JSONResponse, self).__init__(content, mimetype, 
              *args, **kwargs) 

response.pyは、そう私は1つを見つけることができてやりなさいと、ここで助けを求めることにしました。

私が得ることができるヘルプやヒントを読む時間がかかる人に感謝します。

答えて

0

Djangoのドキュメントはreference for thisを持っている:

[特殊パラメータ]一方では、AJAXのPOST要求に使用することができ、それはいくつかの不具合を持っている:あなたは、すべてでCSRFは、POSTデータとしてトークン渡す覚えています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'); 

[...] は最後に、あなたが送信されてからCSRFトークンを保護しながら、実際に、あなたのAJAXリクエストのヘッダーを設定する必要がありますjQuery 1.5のsettings.crossDomainを使用して他のドメインに移動します。1以降:

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); 
     } 
    } 
}); 

あなたが要求を行うために開始する前に、これらの2つのコード・ブロックを実行した場合、それが必要うまく動作™。要約すると

、ちょうどこのコードブロックを使用します。

// 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); 
     } 
    } 
}); 
+0

このコードをすべてjavascriptファイルに置き、dropzoneの '$(function(){});}ロジックの前にエラーを残しています。私はそれをどこか特別に呼び出す必要がありますか? –

+0

Allrightはそれを理解しました。 dropzoneの設定では、ヘッダの値としてクッキーを使用しました。どうもありがとうございました –

0

docsは、DOMではなくクッキーからCSRFトークンを取得することをお勧めします。それを試してください。

+0

助けてもらえている値の余分なフィールドcsrf_tokenを追加する前に

<input type="hidden" name="csrfmiddlewaretoken" value="**************" /> 

を追加し、自動的ですか?私はドキュメントを読んだが、どこでそれを行うのかわからない。 –

1

は自分のHTMLファイルに{% csrf_token %}のどこに配置します。これは、サーバーにデータを送信することはちょうどあなたが私はそれを実装する$("input[name='csrfmiddlewaretoken']").val();

関連する問題