Django not responding back to react - python

I am requesting React frontend to a view in Django (rest framework).
The view in Django will request another server (Google-Ads API), the request works fine and I get the data perfectly. The post-processing of that data also works fine but Django gets stuck after that means It will not run return Response(data).
Django view sample code
def get(self,request):
data = google_api_request(credentials)
data = preprocess(data)
print("end") # this will be executed
return Response(data,status) # this will not be executed
google_api_request code
def google_api_request(credentials):
data = list()
# if I remove this for loop it works
for x in sample_list:
d = google_ads_request(x)
data.append(d)
return data
React sample code:
axiosInstance.get("url").then(
(result) => {
if (result.status == 200) {
console.log("success")
}
}).catch((error) => {
throw error;
})
When I paste the "URL" directly in my browser it works and returns the Response, but only when I run it from react it does not respond.
When I commented google_api_request() code and load the data from a CSV file in the local machine for debugging It returns the Response.
Note: There is no errors message in the console or Django and my CORS setting is correct as other function works fine.
Edit: I found that issue was making requests inside a for a loop.
When I ran only one request without for loop while debugging it worked. so now the question is how to make multiple requests inside Django using for loop. One important thing to note is this problem is only caused when I call the API using React, things work fine when I paste the URL directly in my browser.

Related

How to POST data from python and GET it in NodeJS?

I have a NodeJS server and I want to GET data that is coming from python with the POST method.
pythonData.js
const router = require('express').Router()
router.get("/data",(req,res)=>{
console.log(res)
})
module.exports = router
data.py
import requests
data = {"Car": "BMW","Testing":"API"}
request = requests.post("http://localhost:5000/python/data",data=data)
print(request.status_code)
print(request.text)
but when I run my python file I got an error
404
Error Cannot POST
/python/data
Also how do I get it in my NodeJS
You have implemented a GET method in Node, but you are doing a POST from Python.
Try changing the router.get to router.post in your Express server.
You express router function is processing GET request.
Change this to process POST request.

Django Instagram authentication doesn't work as expected

I have pushed my django project onto pythonanywhere, a free hosting website.
The code works fine in my local and onto the web as well, but somehow have an issue with instagram authentication.
Instagram uses an oauth2 authentication system, in which when the user allows your application, it redirects the user to a specified URI and appends the code inside the URL which further can be used to authenticate the user.
Instagram doesn't allow localhosts as valid redirect URL, therefore for the testing I have used something like this
InstaAuth.html
<script>
history.pushState(null, null, '?code=AQD_4...q6#_');
function reloadThePage() {
window.location.reload();
}
</script>
<button type="submit" class="btn btn-primary" onclick="reloadThePage()">Continue</button>
which changes the state of the url but doesn't actually refresh it. Then I have button which refresh the current page, which directly trigger below code in my views.py and gets the code through request.GET['code'].
Views.py
def instaAuth(request):
if 'code' in dict(request.GET).keys():
code = request.GET['code']
print('the given code is', code)
core = instaCore()
user_id, short_lived_access_token = core.code_to_short_access_with_userid(code_string=code)
print(user_id)
obj = InstaModel.objects.get(username=request.user)
obj.instagram_userid = user_id
obj.short_lived_access_token = short_lived_access_token
obj.is_active = True
obj.save()
print('all data saved!')
messages.success(request, "Your instagram is connected!")
return render(request, 'authentication/success.html')
return render(request, 'authentication/instaAuth.html')
Above code works perfectly fine when I add the code using pushState mehod and refresh the page using button. but when I do the same in my webapp, authorising the app and then clicking continue button, it throughs the KeyError at /instaAuth 'access_token'.
This error usually occurs when someone tries to use the same oauth code more than once. When I looked into the logs I found the error in the same line where I was exchanging the oauth code with the access token. I tried to look into the network tab of the requests, but I am not sure what is missing. I have done similar thing using streamlit and it worked fine, you can check the streamlit app here https://instalogintest.herokuapp.com/
I am stuck at this place, I want to have some logic which either doesn't refresh the page or a way that django knows that this request is coming from Instagram and verify the user using the code.
Problem solved after going through everything for a whole day. Can't believe it was such a small mistake.
I didn't change the redirect uri when I was exchanging the code with access_token.
The problem was I was not printing the error, it always through try and error block, will never do the same again.
Always use this syntax
try
do_something()
except Exception as e:
print(e)
do_something_else()

Capturing variable returned by API in Flask

I'm trying to capture a variable generated by Flask after visiting a certain URL.
I want to use that variable in further authorization in the API.
Due to the nature of Flask, every time the user visits the web app's URL, a function is called that returns a variable.
I want to capture that variable and use it further, without executing the function (the function should be executed only once).
Here's the code I have:
#app.route("/callback/")
def callback_code():
auth_code = request.args.get('code')
return auth_code
code = callback_code()
tracks_endpoint = "https://api.spotify.com/v1/me/tracks"
tracks_auth = {
"Authorization":f"Bearer {code}"
}
tracks = requests.get(tracks_endpoint, headers=tracks_auth)
The problem is caused by:
code = callback_code()
After visiting http://127.0.0.1:5000/auth, Flask displays the following error:
RuntimeError: Working outside of request context.
This typically means that you attempted to use functionality that needed
an active HTTP request. Consult the documentation on testing for
information about how to avoid this problem.
How can I capture auth_code and store it, without executing the function?
Thanks for all your help!
So first problem is that you're expecting the server to be running and get some callback, but the code that is not intended in a function is going to be immeadiately ran, externally from the Flask server lifecycle.
Best way I can think to handle that would be to have your callback redirect to another endpoint, and save off your auth token somewhere in between (such as a session cookie)
Or using a separate variable, for example
AUTH = {
'spotify': None
}
tracks_endpoint = "https://api.spotify.com/v1/me/tracks"
#app.route("/callback/")
def callback_code():
auth_code = request.args.get('code')
AUTH['spotify'] = auth_code
return redirect(url_for('tracks'))
#app.route("/tracks")
def tracks():
if not AUTH['spotify']:
raise('Auth code not loaded. Login first')
tracks_auth = {
"Authorization":f"Bearer AUTH['spotify']"
}
tracks = requests.get(tracks_endpoint, headers=tracks_auth)

Problems with django api on second request

I am working on a flutter app for creating schedules for teachers. I created a Django project to generate a schedule based on the data in the post request from the user. This post request is sent from the flutter app. The Django project doesn't use a database or anything, It simply receives the input data, creates the schedule and returns the output data back to the user.
The problem is that the process of creating the schedule only works 1 time after starting the Django server. So when I want another user to send a request and receive a schedule I have to restart the server... Maybe the server remembers part of the data from the previous request?? I don't know. Is there somekind of way to make it forget everything after a request is done?
When I try to repeatedly run the scheduler without being in a Django project it works flawlessly. The Scheduler is based on the Google cp_model sat solver. (from ortools.sat.python import cp_model). The error I get when running the scheduler the second time in a Django project is 'TypeError: LonelyDuoLearner_is_present_Ss9QV7qFVvXBzTe3R6lmHkMBEWn1_0 is not a boolean variable'.
Is there some kind of way to fix this or mimic the effect of restarting the server?
The django view looks like this:
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from .scheduler.planning import Planning
from .scheduler.planning import print_json
import json
# Convert the data and creates the schedule.
#csrf_exempt
def generate_schedule(request):
if request.method == 'POST':
try:
data = json.loads(request.body)
planning = Planning()
planning.from_json(data)
output_json = planning.output_to_json()
print_json(output_json)
response = json.dumps(output_json)
except Exception as e:
print(e)
print("The data provided doesn't have the right structure.")
response = json.dumps([{'Error': "The data provided doesn't have the right structure."}])
else:
response = json.dumps([{'Error': 'Nothing to see here, please leave.'}])
return HttpResponse(response, content_type='text/json')
There is no beautiful way to restart the server (aside from just killing it by force, which is hardly beautiful).
You're probably using some global state somewhere in the code you're not showing, and it gets screwed up.
You should fix that instead, or if you can't do so, run the solving in a subprocess (using e.g. subprocess.check_call(), or multiprocessing.Process()).
The CP-SAT solver is stateless. The only persistent/shared object is the Ctrl-C handler, which can be disabled with a sat parameter. (catch_sigint if my memory is correct).

Flask JSON request is None

I'm working on my first Flask app (version 0.10.1), and also my first Python (version 3.5) app. One of its pieces needs to work like this:
Submit a form
Run a Celery task (which makes some third-party API calls)
When the Celery task's API calls complete, send a JSON post to another URL in the app
Get that JSON data and update a database record with it
Here's the relevant part of the Celery task:
if not response['errors']: # response comes from the Salesforce API call
# do something to notify that the task was finished successfully
message = {'flask_id' : flask_id, 'sf_id' : response['id']}
message = json.dumps(message)
print('call endpoint now and update it')
res = requests.post('http://0.0.0.0:5000/transaction_result/', json=message)
And here's the endpoint it calls:
#app.route('/transaction_result/', methods=['POST'])
def transaction_result():
result = jsonify(request.get_json(force=True))
print(result.flask_id)
return result.flask_id
So far I'm just trying to get the data and print the ID, and I'll worry about the database after that.
The error I get though is this: requests.exceptions.ConnectionError: None: Max retries exceeded with url: /transaction_result/ (Caused by None)
My reading indicates that my data might not be coming over as JSON, hence the Force=True on the result, but even this doesn't seem to work. I've also tried doing the same request in CocoaRestClient, with a Content-Type header of application/json, and I get the same result.
Because both of these attempts break, I can't tell if my issue is in the request or in the attempt to parse the response.
First of all request.get_json(force=True) returns an object (or None if silent=True). jsonify converts objects to JSON strings. You're trying to access str_val.flask_id. It's impossible. However, even after removing redundant jsonify call, you'll have to change result.flask_id to result['flask_id'].
So, eventually the code should look like this:
#app.route('/transaction_result/', methods=['POST'])
def transaction_result():
result = request.get_json()
return result['flask_id']
And you are absolutely right when you're using REST client to test the route. It crucially simplifies testing process by reducing involved parts. One well-known problem during sending requests from a flask app to the same app is running this app under development server with only one thread. In such case a request will always be blocked by an internal request because the current thread is serving the outermost request and cannot handle the internal one. However, since you are sending a request from the Celery task, it's not likely your scenario.
UPD: Finally, the last one reason was an IP address 0.0.0.0. Changing it to the real one solved the problem.

Categories