HTTP post request in Django - django

I am trying to do the following:
1) A payment solution is supposed to send an HTTP Post to my site
2) I would like to read the contents of the request(xml) and update my records to reflect the payment
I am trying this for the first time. When I create a URL path, and send a post to that address I get the csrf error.
Is there a way using Django wherein I can accept a post and don't have to return a response.
Thanks
Tanmay

Your view should return an http response, otherwise you will get an error. However, Django does not mind if that response does not contain any content. Your view can be as simple as:
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_view(request):
# do something with request.POST
return HttpResponse("")
Since it is a third party that is submitting the post request, and not a user submitting a form on your site, you can mark the view as exempt from CSRF protection using the csrf_exempt decorator, as above.
Note that anyone could submit a post request to your url, so you should have some way of checking that the response is genuine. Your payment solution should be able to advise a suitable way to do this.

Related

Avoid csrf token in django post method

I am making part of the web app where (unlogged users, all visitors) can fill the form and I have to save that data (name, phone number, question) in database..
I am making REST using Django, but for frontend I will use React or Django, and I am making POST method in Django framework that reads JSON data from POST https request, and then I save that data to database.. But I get error CSRF verification failed. Request aborted. because I don not use CSRF token, because it is not required for this (I do not have logged users).
But I do not want to disable CSRF, because for admin page I would use this to authenticate users?
So anyone knows how to avoid using CSRF token for this method? Thanks in advance..
def saveDataToDatabase(request):
if request.method == 'POST':
json_data = json.loads(request.body)
try:
data = json_data['data']
except KeyError:
HttpResponseServerError("Malformed data!")
This is the part of method..
It's possible to disable csrf protection on a view with #csrf_exempt decorator.
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def saveDataToDatabase(request):
# Your code here
More Infos on the Django doc
Have you thought about using Views to handle the requests? You may use these so you don´t have to do the next advice I´m giving you.
If the first advice wasn´t good enough, you may disable the csrf token in the settings file from Django. You need to remove (or comment) the django.middleware.csrf.CsrfViewMiddleware in the available Middleware list.
Any other question just ask. ;)

What is #csrf_exempt in Django?

What is #csrf_exempt, and why should we use this in our views.py? Also, are there any alternatives to it?
Normally when you make a request via a form you want the form being submitted to your view to originate from your website and not come from some other domain. To ensure that this happens, you can put a csrf token in your form for your view to recognize. If you add #csrf_exempt to the top of your view, then you are basically telling the view that it doesn't need the token. This is a security exemption that you should take seriously.
The decorator marks a view as being exempt from the protection ensured by the middleware. Example:
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_view(request):
return HttpResponse('Hello world')
You should not have to use this unless you know exactly why. A good example where it is used is to build a webhook, that will receive informations from another site via a POST request. You then must be able to receive data even if it has no csrf token, but will be replaced by another system of security. For example, if you use stripe for the subscriptions of your clients, you need to know if a client unsubscribed his account. The webhook will be the way to inform your site, and then cut the access to your service for the unsubscribed client.

How to convert a Django HttpResponse to a Django render call

I have the following code
def ajax_login_request(request):
try:
request.POST[u'login']
dictionary = request.POST
except:
dictionary = request.GET
user = authenticate(username = dictionary[u'login'], password = dictionary[u'password'])
if user and user.is_active:
login(request, user)
result = True
else:
result = False
response = HttpResponse(json.dumps(result), mimetype = u'application/json')
return response
which is being called via ajax. I'm a noob and this is from an example in a book. Unfortunately the version of Django I'm using throws a CSRF error on this. I've done the other CSRF bits, but I don't know how to change the HttpResponse bit to a render call. I do not want to use CSRF_exempt, because I have no idea when that is appropriate. Can someone please provide me the equivalent render call for the HttpResponse above.
Thanks
To make your original code work, you need to get a RequestContext object and pass it along with your response, something like this:
from django.http import HttpResponse
from django.template import RequestContext, Template
def ajax_login_request(request):
# ...
# This bit of code adds the CSRF bits to your request.
c = RequestContext(request,{'result':json.dumps(result)})
t = Template("{{result}}") # A dummy template
response = HttpResponse(t.render(c), mimetype = u'application/json')
return response
Do read up on the CSRF documentation as you might run into strange errors if you don't understand all the ways CSRF is "wired" in your app. The page also has a javascript snippet to make sure CSRF cookies are sent with your ajax requests if you are sending them without a form.
You can also use the render_to_response() shortcut, but you would need to have an actual template to load (in your case, you don't need a template, hence the "dummy" template in my example).
Ok, I'm going to re-draft this answer so you understand where I'm coming from. The CSRF middleware works like this:
You make request -------> request hits csrf --(invalid/no token)--> render 403
middleware
|
(valid token)
|
\ /
Call view
|
\ /
middleware sets
csrf cookie
|
\ /
Response appears
In other words, if you are seeing a 403 csrf page, your view was never called. You can confirm this by sticking a spurious print statement in the view and watching the output from runserver when you make your request.
To solve this, you either need to disable csrf (not good) or use one of the ajax methods available to you. If the required token is passed in your view will actually be executed.
The reason your view is not called is to prevent the action from the forged site from actually ever taking place - for example, if you denied the template at response time the user would already be logged in. The same behaviour occurs with the function decorators.
As for the middleware setting the cookie, that does not alter or depend on the render function at all - this sets the HTTP header Cookie: ... in the response. All responses in Django are HttpResponse objects until it finally converts them to output; render functions are helpers, but that's not what's causing your problem here.
Edit I'll convert what you've got to a render call. You could do this:
return render_to_response(`ajax_templates/login_response.html`,
{'loginresponse': json.dumps(result)})
Where ajax_templates/login_response.html is just:
{% loginresponse %}
That's it. HttpResponse has a main default argument which is the string to return (literally, the html of the web page); that's what you're doing initially. render_to_response and render are shortcuts to this which do this:
render_to_response called ----> open template asked for --> substitute arguments
|
\ /
django instructs web server <--- return this from view <-- create HttpResponse
to send to client object

Using flatpages to create a simple facebook app, but CSRF problem caused by signed_request

I am trying to create a simple, html-only facebook app for a client's fb page. I would like to use django's flatpages so that the client and his staff can change the content of the app through the django admin of their site. The problem is that Django returns a 403 "CSRF verification failed. Request aborted." error when facebook attempts to send its own POST info and access the url of the app.
I already know about the #csrf_exempt decorator, but I am not sure how I would apply it to the flatpage view, as it is within the django.contrib code. Furthermore I would only want to disable csrf protection when the view is asked to call a specific facebook.html template (not not the default.html template). If there happened to be a {% crsf_exempt %} template tag for example, that would be perfect.
Can anyone think of a way to resolve this problem? Or maybe I should give up on the idea of using the django-flatpages to serve the facebook app?
Try using this decorator on your views that are called facebook:
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
this will disable csrf protection on that view.
Does this help?
I ran into the exact same problem as you. I wanted to diable csrf for flatpages (but not for the rest of the site) and ended up with the following middleware:
class DisableCSRFOnFlatPages(object):
def process_request(self, request):
try:
FlatPage.objects.get(url=request.META.get('PATH_INFO'))
setattr(request, '_dont_enforce_csrf_checks', True)
except FlatPage.DoesNotExist:
return
Add it to your settings and it should disable the csrf check whenever there's a flatpage.

django request.post

I created a custom "like" button. The "like" is inside a post form html element. For my view.py after i process the form post, i only want to return http response success and not load any type of success page. What kind of object would i return in this case?
Thanks,
David
You'll need to use Javascript to fire an ajax POST request, rather than a standard browser request because the behaviour you're trying to avoid is exactly what a standard request / response cycle does: browser triggers request and displays response as the next page.
Alternatively, you could probably use some kind of iframe, but that'd be just ugly.
You can just return a HTTP response without any content:
from django.http import HttpResponse
return HttpResponse()