I have a Django view where when a user performs a certain task, an external Python microservice retrieves and then sends some data to the Django view, which is supposed to show it to the user on the template. To send the data i'm using Python requests, the problem is that the Json response is being refused by Django for two reasons: 1) The CSRF Token is not set 2) The view is @login_required
Here is my view:
@login_required
def myTestView(request):
if request.method == 'POST':
received_json_data=json.loads(request.body)
print(received_json_data)
print('received.')
And here is how i send the response:
import requests
req = requests.post('http://127.0.0.1:8000/myTestView/', json={"test": "json-test"})
print('SENT')
With the actual code, i get this error from Django:
Forbidden (CSRF cookie not set.): /myTestView/
[2019-12-24 15:36:08,574] log: WARNING - Forbidden (CSRF cookie not set.): /myTestView/
I know i can use @csrf_exempt, but since the data that i'm sending is personal, i would like it to be as safe as possible, so i need to find a way to send the CSRF Token. The second thing i need to do, is how do i "login" using the request?
I like this question, so I'll try to describe the whole process in detail.
First step is to get csrf_token which you'll use in the further post request.
After that you have to authenticate the session.
So let's write a view to serve get for getting csrf_token and post for authenticating session. The same idea for protected view.
After we get authenticated it is possible to access protected view.
import json
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, HttpResponseForbidden
from django.middleware.csrf import get_token
@login_required
def myTestView(request):
if request.method == 'POST':
data = request.POST.get('data')
print(json.loads(data))
print('received.')
response = HttpResponse(get_token(request))
return response
def login_view(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return HttpResponse('authenticated')
else:
return HttpResponseForbidden('wrong username or password')
response = HttpResponse(get_token(request))
return response
requests.post does not fit for this task because it can't track (or it's really hard) request cookies and headers.
But you can use for this purpose requests.session()
Django is not able to process csrf_token in json, that's why you have to pass json in request data.
import json
import requests
session = requests.session()
token = session.get('http://127.0.0.1:8000/login/')
session.post('http://127.0.0.1:8000/login/',
data={
'username': '<username>',
'password': '<password>',
'csrfmiddlewaretoken': token})
token = session.get('http://127.0.0.1:8000/myTestView/')
data = json.dumps({'test': 'value'})
session.post('http://127.0.0.1:8000/myTestView/',
data={
'csrfmiddlewaretoken': token,
'data': data})
Mind adding urls.py for the views
I checked this code and it is working well. If anyone has an ideas how to improve it I will love to update it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With