user3974637
user3974637

Reputation: 25

Dropzone Js csrftoken

I have a django template with a form element that includes some input text edit and a submit button and a user avatar uplaoder with DropzoneJS. The problem is that I can't put DropzonJs in a div in my form Becuase it raise a csrf_token error. When I put an csrf_token in my div for dropzoneJS; nothing changes. What I have found yet us that csrf_token only works with HTML form element. Here is my template:

<form role="form" method="POST">
    {% csrf_token %}
    <h5>Edit Profile Details</h5>
    <div class="content">
        <h1>{{ username }}</h1>
        <!-- My other fields here -->
        <div class="m-b-sm">
             <img alt="image" class="img-circle" src="{% static 'img/profile.jpg' %}" />
        </div>
        <!-- Here is the div that contains DropzoneJS -->
        <div class="dropzone dropzone-previews" id="my-awesome-dropzone" action="">
            {% csrf_token %}
        </div>
    </div>
    <!-- ... -->

What I think yet was if I put a {% csrf_token %} in my form, there is no need to add some other {% csrf_token %} in its inner elements.

DropzoneJS works with form like this:

<form class="dropzone" action="{% url "test_avatar" %}" method="post" enctype="multipart/form-data" id="my-awesome-dropzone">
   {% csrf_token %}
</form>

But I can't use this form inside of my form Because of the error of nested HTML form elements. What should I do?

Upvotes: 1

Views: 2511

Answers (2)

Edward Newell
Edward Newell

Reputation: 18449

Dennis' answer is a good clue, but you'll need a couple more details to get there. You'll be making your Dropzone programatically on a non-form HTML element, and then adding the CSRF token to the data it sends during file uploads.

(BTW, if you use AJAX elsewhere on your site, you probably use a framework (jQuery) hook to attach the CSRF token to all AJAX posts --- but Dropzone isn't using your framework, which is why it doesn't get the CSRF token.)

Here we go. Use a regular div (or other non-form HTML element) as the Dropzone:

<div id="my_dropzone"></div>

Define a function in JavaScript that will help you grab the CSRF token:

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

Make your Dropzone. Use the params field to send the CSRF token during file uploads:

var my_dropzone = new Dropzone('#my_dropzone', {
    'url': '/avatar-upload', # url for view that handles upload
    'params': {'csrfmiddlewaretoken': getCookie('csrftoken')}
})

Upvotes: 3

Dennis Spieker
Dennis Spieker

Reputation: 31

You should create your dropzone instance programmatically and append the csrf_token to the formData object.

First, store the token in a javascript variable somewhere in your html:

(I use PHP/Laravel myself so I'm not sure if this prints out the token but you get the idea..)

<script>
   token = {% csrf_token %};
</script>

Then in your javascript file (or inline) create the dropzone instance:

var myDropzone = new Dropzone(".dropzone", {
   url: '/file/upload', // your test_avatar route here
   sending: function(file, xhr, formData) {
      formData.append("csrf_token", token);
      // the first parameter should be the fieldname that django is looking for
      // the second parameter being the token from the variable set in your html
   },
});

Upvotes: 3

Related Questions