I can't do a POST ajax request in Django. If I do a GET request, it works fine. I think it may be a csrf token problem, but I can get it to work
My view:
#login_required
def add_share_points(request):
user = request.user
profile = request.user.profile
if request.method == 'POST':
value = 5.0
# Premia o usuário ao compartilhar conteúdo
VirtualCurrencyTransaction.objects.create(
user=request.user,
reason=2,
description='Você completou seu perfil',
value=value
)
return "ok"
My AJAX request:
$('.my-button').on('click', function(e) {
e.preventDefault();
var pointsCount = $(this).hasClass('homepage-facebook-share') ? 3 : 2;
$.ajax({
type:"POST",
url: "/add_share_points",
data: {
points: pointsCount,
}
}).done(function() {
alert('Posting completed.');
}).fail(function(){
alert('Error while posting.');
});
});
In my script, I also have this setting:
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/).test(method);
}
$.ajaxSetup({
crossDomain: false,
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader('X-CSRFToken', CSRF_TOKEN);
}
}
});
What is wrong with my code? It gave my a 500 error code, but no further explanation in the logs.
I will point out several things to correct, some are just ways to do it in a django manner and not problems.
In your view
return HttpResponse(
json.dumps({'result': 'ok',}),
content_type="application/json"
)
In your ajax
url: "/add_share_points",
should be:
url : {% url '<name in url.py>' %},
and you need to add (to the data object):
csrfmiddlewaretoken: '{{ csrf_token }}'
Inside the ajax request, insert this after data:
// handle a successful response
success : function(json) {
if (json.result=== 'ok'){
console.log('It works!');
}else{
console.log('Something wrong with response');
}
// handle a non-successful response
error : function(xhr,errmsg,err) {
console.log(err);
}
In your script
instead of CSRF_TOKEN use '{{ csrf_token }}'
Please use my suggestions and give me feedback and I will update the answer. The two with csfrtoken are probably the problems your having. If you put Django in Debug mode it will be easyer to find out.
My Suggestion
Create a form with what you need to post to gain some features in the validation process.
Related
I have a script in my template that tries to send data to a django view during onbuttonclick event. My problem is that the request doesn't seem to make it to the view. The browser console sees the request properly and all, but the django view does't even return true when i call request.is_ajax().
request.method returns GET instead of POST, and the data is empty. This behavior is persistent regardless of the request type.
html
<a onclick="setGetParameter(this)" pid="some_id">Some Text</a>
.js
<script>
var csrftoken = Cookies.get('csrftoken');
function setGetParameter(el){
var stuff = $(el).attr('pid');
$.ajax({
type: 'POST',
headers: { "X-CSRFToken": csrftoken },
url: '/view_url/',
data: {'datatopass': stuff},
success: function(response){
alert(response);
}
});
}
</script>
urls.py
path('view_url/', views.test),
path('', views.home),
views.py
def test(request):
output = request.is_ajax()
return HttpResponse(output)
In Django 3.1 is_ajax() method is deprecated. See Miscellaneous Django 3.1
So for Django >= 3.1 you can do it like that:
if request.headers.get('x-requested-with') == 'XMLHttpRequest':
is_ajax = True
else:
is_ajax = False
And make sure that the following line added in AJAX request headers:
"X-Requested-With": "XMLHttpRequest"
I would be use jQuery click method:
<a pid="some_id">Some Text</a>
<script>
var csrftoken = Cookies.get('csrftoken');
function setGetParameter(el){
var stuff = $(el).attr('pid');
$.ajax({
type: 'POST',
headers: { "X-CSRFToken": csrftoken },
url: '/view_url/',
data: {'datatopass': stuff},
success: function(response){
alert(response);
}
});
}
$(document).ready(function(){
$('a[pid]').click(function(){
setGetParameter(this);
});
});
</script>
Also I would be use JsonResponse objects:
from django.http import JsonResponse
def test(request):
output = request.is_ajax()
return JsonResponse({'is_ajax': output})
In order to serialize objects other than dict you must set the safe parameter to False:
response = JsonResponse([1, 2, 3], safe=False)
After days of beating my head against a wall, I chose to go with a different implementation. It appears I can only render the data on the page that initially sent the request.
i am posting javascript localstorage object to backend(django). I am passing it through ajax.
this is the code in frontend.
function checkout_(){
console.log("checkout");
for(v in list1){
object=Object.values(localStorage)[v];
object = JSON.parse(object)
}
//ajax here
console.log(object.length);
$.ajax({
url: '{% url "chout" %}',
data: {
'object': object
},
method: "POST",
dataType: 'json',
success: function (data) {
alert("success");
}
});
i have given this function to a button via onclick.
<button class="bg-danger text-white " onclick="checkout_()">Go To Checkout Counter</button>
when i click on this button this error "Failed to load resource: the server responded with a status of 403 (Forbidden)" happens.
in the views.py this is the code.
views.py
def checkoutnow(request):
return render(request, "mart/checkout.html")
I hope this detail is enough to explain the problem..Thankyou
You have to pass csrfmiddlewaretoken also in the post call because of csrf middleware set in the settings
const csrf = "{{ csrf_token }}";
and add this key, value pair to your data:
data: {'csrfmiddlewaretoken':csrf, 'object': object },
You can skip this and just use GET instead of POST if feasible.
Ajax method to post and passing a string to the views.py, the post method in the views.py can receive values from ajax but I cannot get the results value to print back in the ajax success method.
I have tried to return HTTPresponse, redirect, render but nothing seem to work for me.
//Ajax//
$("#viewData").click(function(event){
$.ajax({
type: "POST",
data: {
tempData : "permView",
csrfmiddlewaretoken: '{{ csrf_token }}',
},
success: function(result) {
console.log('{{ result }}')
},
});
event.preventDefault()
});
});
//Python//views.py
class SpreadSheetView(TemplateView):
template_name = 'spreadsheet.html'
def get(self, request, *args, **kwargs):
return render(request, self.template_name, {'type': '86'})
def post(self, request):
if request.POST['tempData'] == 'permView':
return render(request, self.template_name, {'result': "test result"})
You are encountering one of these two problems:
You might be getting an error in your view and cannot notice it since you do not cover error case in your ajax request. Just update your ajax request call like this and see if you are getting an error.
You are not specifying dataType parameterto your request, which causes ajax to incorrectly guess your response type.
To cover these two items, update your request such as:
$.ajax({
type: "GET",
dataType : 'html', # or other types, depending on your needs.
data: {
tempData : "permView",
csrfmiddlewaretoken: '{{ csrf_token }}',
},
success: function(data, status) {
console.log(data)
console.log(status)
},
error: function(xhr, status, error) {
console.log(status);
console.log(error);
}
});
I have previous experience in Django. If add line {csrf_token} in Django templates then Django handles the functionalities of csrf_token. But when I am trying to develop an API using Django REST Framework then I get stuck. How can I add and handle functionalities like csrf_token in API (back end, developed using Django REST Framework) and React Native/React JS (front end) like Django templates?
The first step is to get CSRF token which can be retrieved from the Django csrftoken cookie.
Now from the Django docs you can find out how to get the csrf token from the cookie by using this simple JavaScript function:
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]);
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
Now, you can retrieve the CSRF token by calling the getCookie('csrftoken') function
var csrftoken = getCookie('csrftoken');
Next you can use this csrf token when sending a request with fetch() by assigning the retrieved token to the X-CSRFToken header.
fetch(url, {
credentials: 'include',
method: 'POST',
mode: 'same-origin',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: {}
})
}
Rendering the CSRF Token in React Forms:
If you are using React to render forms instead of Django templates you also need to render the csrf token because the Django tag { % csrf_token % } is not available at the client side so you need to create a higher order component that retrieves the token using the getCookie() function and render it in any form.
Lets add some line in csrftoken.js file.
import React from 'react';
var csrftoken = getCookie('csrftoken');
const CSRFToken = () => {
return (
<input type="hidden" name="csrfmiddlewaretoken" value={csrftoken} />
);
};
export default CSRFToken;
Then you can simply import it and call it inside your form
import React, { Component , PropTypes} from 'react';
import CSRFToken from './csrftoken';
class aForm extends Component {
render() {
return (
<form action="/endpoint" method="post">
<CSRFToken />
<button type="submit">Send</button>
</form>
);
}
}
export default aForm;
The Django CSRF Cookie
React renders components dynamically that's why Django might not be able to set a CSRF token cookie if you are rendering your form with React. This how Django docs says about that:
If your view is not rendering a template containing the csrftoken
template tag, Django might not set the CSRF token cookie. This is
common in cases where forms are dynamically added to the page. To
address this case, Django provides a view decorator which forces
setting of the cookie: ensurecsrf_cookie().
To solve this issue Django provides the ensurecsrfcookie decorator that you need to add to your view function. For example:
from django.views.decorators.csrf import ensure_csrf_cookie
#ensure_csrf_cookie
def myview(request):
I used jquery for ajax in react, so in this case here is a solution :
let csrfcookie = function() { // for django csrf protection
let cookieValue = null,
name = "csrftoken";
if (document.cookie && document.cookie !== "") {
let cookies = document.cookie.split(";");
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) == (name + "=")) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
};
$.ajax({
type: "POST",
beforeSend: function(request, settings) {
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
request.setRequestHeader("X-CSRFToken", csrfcookie());
}
},
.... /// other codes
I'm working on a project in which I'm using Python(3.6) & Django(1.10) and I need to implement Paypal payment method in this project. I have decided to use the official Python SDK from Paypal instead of other third-party packages.It's not only the csrf problem but it also how we can render a custom form for paypal checkout button.
Here's wwhat Ihave tried.
According to the docs as Here.
Here's my template:
<form class="form">
{% csrf_token %}
<div id="paypal-button"></div>
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
<script>
var CREATE_PAYMENT_URL = '{% url 'users:payment' %}';
var EXECUTE_PAYMENT_URL = 'https://my-store.com/paypal/execute-payment';
paypal.Button.render({
env: 'sandbox', // Or 'production'
commit: true, // Show a 'Pay Now' button
payment: function () {
return paypal.request.post(CREATE_PAYMENT_URL).then(function (data) {
return data.paymentID;
});
},
onAuthorize: function (data) {
return paypal.request.post(EXECUTE_PAYMENT_URL, {
paymentID: data.paymentID,
payerID: data.payerID}).then(function () {
// The payment is complete!
// You can now show a confirmation message to the customer
});
}
}, '#paypal-button');
</script>
</form>
From urls.py:
url('^payment/$', views.PaymentProcess.as_view(), name='payment'),
From views.py:
class PaymentProcess(LoginRequiredMixin, generic.DetailView):
def post(self, request, *args, **kwargs):
mydict = {
'paymentID': 'PAYMENTID',
}
print('Getting payment request')
return json.dumps(mydict)
When Paypal submits a post request to /payment it returns 403 Forbidden error due to csrf_token. How can I pass the csrf_token with this request.
Any resource or tutorial will be really appreciated.
It seems you can add custom headers to your post request : https://github.com/paypal/PayPal-Python-SDK/blob/master/paypalrestsdk/api.py#L270
Given that you just have to add you csrf token to the headers : https://docs.djangoproject.com/en/2.0/ref/csrf/#setting-the-token-on-the-ajax-request
And your server should give you access