Reputation: 25
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
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
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