Post data isn't be sent with jquery / django - django

I'm trying to perform a simple post to django that will take in a variable and then redirect the user to another page. Right now, my javascript looks like this:
$.ajax({
type: "POST",
url: "{% url unity.survey.views.post %}",
data: { // <-- error here?
'order' : '1',
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function(datas) {
if (datas.redirect) {
window.location.href = data.redirect;
}
}
});
};
My corresponding view in django looks like so:
def post(request, *args, **kwargs):
if 'order' in request.POST:
order = request.POST['order']
else:
return redirect('unity.survey.views.login')
.... some calculations with order ....
return render_to_response(
'template.html',
some_dictionary,
context_instance=RequestContext(request)
)
For some reason, it appears that nothing is sent to the view. Looking at Firefox's web console, I see:
[07:31:12.414] POST http://127.0.0.1/unity/ survey/ [undefined 17ms]
[07:31:12.422] GET http://127.0.0.1/unity/survey/ [HTTP/1.1 302 FOUND 73ms]
[07:31:12.497] GET http://127.0.0.1/unity/survey/login [HTTP/1.1 200 OK 177ms]
It just redirects me to the login page regardless of what I do. I've tried using .post instead of .ajax, but it results in the same thing. Any idea why this might be the case? I have a similar function and it works great but for some reason I can't get this to work. It just appears as if no POST data is being sent.

Related

Django with Javascript fetch API: POST works but all other unsafe methods are forbidden

I am working on this CS50W project.
When using the fetch API to send POST requests to the server, everything worked fine.
After I changed the method to PUT, or any other unsafe methods, things stopped working.
Javascript
let like_form = document.querySelector('#like-form');
let data = new FormData(like_form);
fetch(`post/${post_id}/like`, {
method: 'POST',
body: data,
credentials: "same-origin"
})
views.py
#login_required
def like_post(request, post_id):
if request.method == 'POST':
post = get_post(post_id)
if post:
if request.user in post.liked_by.all():
post.liked_by.remove(request.user)
status = False
else:
post.liked_by.add(request.user)
status = True
return JsonResponse({
'message': 'Success.',
'status': status
}, status=200)
index.html
<form id='like-form'>
{% csrf_token %}
</form>
Output using POST
{message: 'Success.', status: false}
Output using PUT
PUT http://127.0.0.1:8000/post/17/like 403 (Forbidden)
Forbidden (CSRF token missing.): /post/17/like
The only thing I changed was the method in fetch and views.py
Any help will be appreciated.
After going into the source code, I found out that for PUT, the csrf_token is read from the headers of the request instead of the body. Therefore adding
headers: {
'x-csrftoken': CSRF_TOKEN_ELEMENT.value
}
solved the problem

Django redirect is not working with dropzone.js

Redirect in Django is not working when files are uploaded using Dropzone.js, so I used windows.href in the Dropzone success event but I have to pass a parameter.
views.py:
if request.method == 'POST' and request.FILES['files']:
...
if form.is_valid():
....
user = User.objects.get(email=email)
id = user.id
return redirect(reverse('success', kwargs={'id': id})) <<-- not working
JQuery - Dropzone:
this.on('success', function() {
window.location.href = '/success/';
})
I don't reckon there is a way to pass the id to JQuery in this case, so I have to use redirect in Django. How can it get done?
The reason why django redirect is not working is because dropzone.js uses AJAX for its post requests which doesn't redirect pages.
To get the redirect to work you need to get the dropzone to redirect with javascript to the correct url given as a response from the POST request. The view returns a JSON response that then can be parsed from the js. This is done as follows:
from django.http import JsonResponse
def index(request):
if request.method == 'POST':
form = BenchmarkForm(request.POST, request.FILES)
if form.is_valid():
model_id = YourModel.objects.create(file=request.FILES['file']).id
link = reverse('energy:benchmark',kwargs={'id':model_id})
response = {'url':link}
return JsonResponse(response)
Then in the dropzone init function you need to parse the response in the success callback.
Dropzone.options.myDropzone = {
// Prevents Dropzone from uploading dropped files immediately
autoProcessQueue : false,
url: "{% url 'energy:index' %}",
headers: {
"X-CSRFToken": "{{ csrf_token }}"
},
init : function() {
mydropzone = this;
this.on("success", function(file, response) {
window.location.href=JSON.parse(file.xhr.response).url
});

Post request in Django results in broken pipe

I'm trying to make a post request from a react frontend to a django backend to log a user in, and redirect to a new page. The issue I'm having is that even though the request reaches the server and I can get the data when it comes time for django to redirect, the redirect does not happen and their is an output in the console that says "Broken pipe from ('127.0.0.1', 64989)". I've done some research online about this issue, but I still can't figure out how to fix it. However, everything works fine when I use a an html form element with an action and method type. Below I have shared my code.
React Frontend
handleSubmit = () => {
let csrfToken = Cookies.get('csrftoken')
let endpoint = this.state.isLoggingIn ? LOGIN_ENDPOINT : REGISTER_ENDPOINT;
axios({
url: endpoint,
method: "POST",
data: {
username: this.state.username,
password: this.state.password,
displayName: this.state.displayName,
},
headers: {"X-CSRFToken": csrfToken},
responseType: "json",
}).then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});
}
Django Backend
def login_view(request):
if request.method == 'POST':
#username = request.POST.get('username') <= I use this and below, to get data sent via a form with an action and method set.
#password = request.POST.get('password')
body_unicode = request.body.decode('utf-8')
data = simplejson.loads(body_unicode)
username = data['username']
password = data['password']
user = authenticate(username=username, password=password)
print user
if user is not None and user.is_active:
login(request, user)
return redirect('chat_app:chat')
else:
return JsonResponse({'message': 'Check you username or password'})
else:
return render(request, 'frontend/chat_app/home.html')
Following works but is not what I want
With this method I can get the data from the input fields (not shown here)
authenticate the user and redirect them properly. However, I do not want to
use this method because I want to pass back any error messages to the submitFunction() that had been called, or process any other data, in the same page that had made the call.
<form method="POST" action={ENDPOINT}>
<input
type="hidden"
name="csrfmiddlewaretoken"
value={csrftoken}
/>
....

how to update request.user in django?

I have an ajax call which sets
request.user.my_field = value
When the ajax succeeds, I reload the page with location.reload(True)
I expect the request.user.my_field in the view function is updated now but it has the old value.
How can I fix this?
EDIT
The ajax call:
$.ajax({
type: 'POST',
url: '{% url editor_select %}',
data: {'editor_type':$(this).val(),
success: function(response_data) {
location.reload(true);
}
}
});
The first view:
def editor_select(request):
"""
called when user changes editor type to post question/answer
"""
editor_type = CharField().clean(request.POST['editor_type'])
request.user.editor_type = editor_type
request.user.save()
The second view:
def second_view(request):
print 'ask, editor_type:', request.user.editor_type
I find AuthenticationMiddleware (which sets request.user to request), doesn't get called in between the ajax call and the location.reload()
so umm???
Save the model before exiting the view.
request.user.save()
Wow shoot me..
success: was inside data and it requested two pages in succession.

Django CSRF on 500 error page with a form

I got a 500 error page which has a form, however the CSRF token is not generated when 500 error page is thrown. What's the best way to generate the CSRF token on a 500 error page to make the form post work? Should I just define my own custom 500 error view?
OK, I tried defining the custom 500 view and worked, for anyone who has the same issue, here it's how:
define a custom 500 error view
from django.shortcuts import render
def server_error(request):
vars = {}
return render(request, '500.html', vars, status=500)
then in the main urls.py add:
handler500 = 'your_app.views.errors.server_error'
You have to pass the token on the ajax request
var data = {
errorresponse: errorresponse,
'csrfmiddlewaretoken': '{{ csrf_token }}',
}
$.ajax({
type: "POST",
url: "/your-target-url/",
data: data, // this passes data context into view
success: function(data) {