Send a request with Django view using Python-Requests - python

I'm trying to create a simple microservice structure on my Django projecjt: so when a certain Django view is called, this view will send a JSON post request to a Flask microservice containing some user's data; the Flask microservice should receive the request, take that user's data and send back to Django some additional data using Requests again, so that my Django view can receive that data and perform some operations, such as showing it to the user.
Right now i'm just sending some dummy data, to test if this whole system ( Django > request to Flask > Flask > Request to Django) works, but i'm having some problems.
To debug my code, i'm trying to just print the received data. Here is my view:
def myView(request):
mydict = {}
# The request is sent to my external Python script..
req = requests.post('http://127.0.0.1:5000/', json={"one": 1}) # Some dummy data
# .. Once the external script sends back a request with data, this should handle it
if request.method == 'POST':
# The data is inside this variable
data = request.POST
for key in data.items():
if float(key[1]) > 0:
mydict.update({key[0]: key[1]})
print(mydict) #FIRST PRINT STATEMENT
print(mydict) #SECOND PRINT STATEMENT
response = HttpResponse(get_token(request))
return JsonResponse(mydict) #RETURNS "{}"
And here is how my Flask app sends data (once it receives the POST request from the Django view) using the Python-Requests library:
#app.route("/", methods=["GET","POST"])
def test():
# After the request from the VIEW is received, a request containing some random json data
# is sent to Django
url = 'http://127.0.0.1:8000/myView/'
client = requests.session()
# We need to get the CSRF token, in order for the request to be taken by Django
csrftoken = requests.get(url).cookies['csrftoken']
data = {"two": 2}
header = {'X-CSRFToken': csrftoken}
cookies = {'csrftoken': csrftoken}
resp = requests.post(url, data=data, headers=header, cookies=cookies)
# Let's seend the request to Django
return f"Test!"
Here is what's wrong with my code:
METHOD: POST
{'two': 2}
[10/Jan/2020 10:41:37] "POST /myView/ HTTP/1.1" 200 320
{}
[10/Jan/2020 10:41:37] "GET /myView/ HTTP/1.1" 200 2
Here is what's wrong:
Why does the first print statement return the correct data and why doesn't the second print? And why does return JsonResponse return an empty dictionary?
I tried to add print('METHOD: ', request.method) in the first lines of the view, here is what happened:
METHOD: GET
METHOD: GET
[10/Jan/2020 10:46:22] "GET /myView/ HTTP/1.1" 200 2
METHOD: POST
[10/Jan/2020 10:46:26] "POST /myView/ HTTP/1.1" 200 320
[10/Jan/2020 10:46:26] "GET /myView/ HTTP/1.1" 200 2

You're flask view can be simplified to just return the required data
#app.route("/", methods=["GET","POST"])
def test():
return {"two": 2}
Then you can use the data in the Django view after you have made the request to flask
response = requests.post('http://127.0.0.1:5000/', json={"one": 1})
print(response.json()) # This should contain the returned data

Related

How to send data from localhost to server using Python requests?

I am trying to send data from localhost to an API in remote server using Python Requests & Django through an API: /api/send-data/
Path for /api/send-data/ in urls.py is path('send-data/',view_send_data.send_data,name='send_data')
This is my view_send_data.py in my localhost:
#api_view(('POST',))
#renderer_classes((TemplateHTMLRenderer, JSONRenderer))
def send_data():
# defining the API-endpoint
API_ENDPOINT = "http://68.183.89.234/api/screen/"
# data to be sent to API
data = {'data':1234}
# sending post request and saving response as response object
r = requests.post(url = API_ENDPOINT, data = data)
print(r.json())
return Response({"success": True}, status=status.HTTP_200_OK)
Path for api at http://68.183.89.234/api/screen/ in urls.py is path('screen/',views_fr.screen_display,name='screen')
This is my views_fr.py in my remote server:
#api_view(['POST'])
def screen_display(request):
if request.method == 'POST':
return Response({"success": True,
"response": request.data}, status=status.HTTP_200_OK)
When I call "http://127.0.0.1:8000/api/send-data/" in my browser, I am getting 405 Method Not Allowed
Is this the correct way to do it or am I missing something? Thank you.
The error you are getting is because the remote server API only accepts POST method, but you can't make a POST request using the browser url call. Test the API using postman or curl so you can set the correct method for request.

Django view doesn't receive Json data?

Using a simple Python script, i want to send a request, with Python-Requests, to a Django view. The Django view should receive the json data inside the request and should print it to my console; here is what i tried:
This is how i send the request:
url = 'http://127.0.0.1:8000/myview/view'
client = requests.session()
csrftoken = requests.get(url).cookies['csrftoken']
data = json.dumps({'data': 'test-value'})
header = {'X-CSRFToken': csrftoken}
cookies = {'csrftoken': csrftoken}
resp = requests.post(url, data=data, headers=header, cookies=cookies)
And this is how the Django view receives it:
def myview(request):
if request.method == 'POST':
data = request.POST.get('data')
print(data)
print('received.')
response = HttpResponse(get_token(request))
return response
The problem with my current code is that print(data) will throw the following output:
None
received.
[06/Jan/2020 21:23:57] "POST /myview/view HTTP/1.1" 200 64
So, instead of printing test-value, it prints nothing. I don't understand whether the error is in my Django view or in how i'm sending the request. Any advice is appreciated!
The problem is with your request, and entirely caused by this line:
data = json.dumps({'data': 'test-value'})
You simply want
data = {'data': 'test-value'}
The POST data should be sent as a simple dictionary, not a JSON string - see the documentation and example here.

How do i log-in with a POST request in a Django view?

On a certain page of my Django project, i'm trying to add a feature where, when a page is loaded, a request is sent to an external Python script, this Python script will retrieve some data and send it as a response to the Django view, which should show it on the HTML using Jquery. To send the requests, i'm using the Request module.
I'm having some problems sending the response with the Json data to the Django view, here is what i tried:
Here is how the request is sent:
import requests
req = requests.post('http://127.0.0.1:8000/myview', json={"test": "testjson"})
print('SENT')
What i tried in the view:
def myTestView(request):
if request.method == 'POST':
received_json_data=json.loads(request.body)
print(received_json_data)
print('Received request')
I'm trying to print the response in my console just for debugging purposes. The problem is that i don't see the request being printed in the console. Instead, i only see this:
[24/Dec/2019 12:00:40] "POST /tv/ HTTP/1.1" 302 0
[24/Dec/2019 12:00:40] "GET /account/login/?next=/tv/ HTTP/1.1" 200 23357
Which means that i have to add my credentials, since the view is #login_required. The problem is that this request is fired when the user loads the page or performs a certain operation, and the request will hold sensitive data. This task, however, can be performed by any user on the site, so i can't add the credentials of only one in my external request. How can i fix this? Any advice is appreciated

302 redirection error before 200 success code IN FLASK

I am running an FLASK app where I check the JWT in the index endpoint. The problem was I get 2 response when I execute this end point .
127.0.0.1 - - [06/Dec/2018 17:38:21] "GET / HTTP/1.1" 302 -
127.0.0.1 - - [06/Dec/2018 17:38:21] "GET /home HTTP/1.0" 200 -
My code is
#app.route('/')
def index():
try:
encoded_jwt=request.headers.get('jwt')
print(encoded_jwt)
secret = "-----BEGIN PUBLIC KEY----- ........"
claims = jwt.decode(encoded_jwt, secret)
print(type(claims))
import json
json_parse = json.loads(json.dumps(claims))
email = json_parse['http://wso2.org/claims/emailaddress']
print(email)
roles = json_parse['http://wso2.org/claims/role']
print(roles)
session['email'] = email
if ROLETAGOFADMIN in roles:
role="admin"
elif "" in roles:
role = "employee"
else:
role=None
session['role'] = role
if 'email' in session and (session['role'] == "admin" or session['role'] == "employee" )and request.method == "GET":
if 'lastpage' in session:
lastpage=session['lastpage']
print(lastpage)
session.pop('lastpage')
return redirect(lastpage)
else:
return redirect(url_for('home'))
else:
return "Sorry. Unfortunately You have no access."
except Exception as e:
return redirect(url_for('error'))
My Identity server is redirecting because of the first response. I couldn't find the way to fix that. I am not aware of that the error is occurred because of the try catch . Please help me.
You are using Flask's redirect to issue a redirect which is going to send a 302 response to the client with a Location header instructing the client to go to /home instead. Then the client has to issue the request to this new URL where the client finally gets the 200 response code. That is why you are seeing two requests and the 302 and 200 response codes in the server logs.
This particular line is causing the redirect:
return redirect(url_for('home'))
It seems like you expected redirect to simply render the content of /home and return that as the response with the original request to / (e.g. a single 200 response). If that's what you actually want, you could instead use render_template (or whatever you use in /home to render your content) to directly render that page. However, I would recommend keeping the redirect behavior as you have it.

hosting an image with the flask and then processing the same using another view function in the same code

so I am hosting an image using flask and then I want to do a post request to an API using the url all in the same code:
#app.route('/host')
def host():
return send_from_directory("C:/images", "image1.png")
#app.route('/post')
def post():
response = requests.post(url, data={'input':'<url for host>', headers=headers)
return jsonify(response.json())
I believe as both these view functions are in the same python file, post() gets blocked.
Is there a workaround this problem ?
PS: if I host images on a different machine, it works, but that's not what I desire.
Thanks!
I think there are some problems with your code.
First, I don't believe there is an #app.post() decorator in Flask. My guess is that you were trying to specify that that route should be POSTed to by your users. The way to do that would be #app.route('/post', methods=['POST']).
Next, it seems like you want the /post endpoint to send a POST request to a user-specified(?) URL when the user sends an HTTP request to this endpoint. The way you would do that for a user-specified / user-POSTed URL is something like this (I haven't run this code to test it):
#app.route('/send_post_request', methods=['POST'])
def send_post_request():
user_posted_data = json.loads(request.data)
user_specified_url = user_posted_data['url']
dict_to_post= { 'input': url_for('hosts') }
headers = {} # Fill these in
response = requests.post(user_specified_url , json=dict_to_post, headers=headers)
return jsonify(response.json())
If the URL to send the POST request to is known by the server, you could have your user simply send a GET request:
#app.route('/send_post_request', methods=['GET'])
def send_post_request():
dict_to_post = { 'input': url_for('hosts') }
headers = {} # Fill these in
server_specified_url = '' # Fill this in
response = requests.post(server_specified_url, json=dict_to_post, headers=headers)
return jsonify(response.json())

Categories