Flask is caching the returned response - python

i have an app that return a json response (no HTML).
the problem is the response get cached like the following.
from flask import jsonify, make_response
# base api template
baseApi = {'status':None, 'message':None, 'data':{}}
#app.route('/getdata1')
def getData1():
result = baseApi.copy()
result['status'] = 'success'
result['data'] = {'data1':'some data'}
return make_response(jsonify(result), 200)
#app.route('/getdata2')
def getData2():
result = baseApi.copy()
result['status'] = 'success'
result['data'] = {'data2':'some other data'}
return make_response(jsonify(result), 200)
if i go to the link /getdata1 then the rsponse will be as i expected
{
"data": {
"data1": "some data"
},
"message": null,
"status": "success"
}
but if after that i run the link /getdata2 i got the two results back
{
"data": {
"data1": "some data",
"data2": "some other data"
},
"message": null,
"status": "success"
}
NOTE : the cache not happen in the browser , i have a mobile app , if i go to /getdata1 in the mobile and then try /getdata2 in the PC i got the same thing.
i tried this but it not seem to work !
#api.after_request
def after_request(response):
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate, public, max-age=0"
response.headers["Expires"] = 0
response.headers["Pragma"] = "no-cache"
return response
thanks a lot!!

i guess you should try to use a deepcopy instead of shallow copy of your dictionnary.
the problem is not the cash but rather the dictionary has the same reference :
if we read about the definition of shallow copy
A shallow copy creates a new object which stores the reference of the original elements.
To get a fully independent copy of an object you can use the copy.deepcopy() which is the case of this question.

Related

Reading key values a JSON array which is a set in Python

I have the following code
import requests
import json
import sys
credentials_User=sys.argv[1]
credentials_Password=sys.argv[2]
email=sys.argv[3]
def auth_api(login_User,login_Password,):
gooddata_user=login_User
gooddata_password=login_Password
body = json.dumps({
"postUserLogin":{
"login": gooddata_user,
"password": gooddata_password,
"remember":1,
"verify_level":0
}
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
url="https://reports.domain.com/gdc/account/login"
response = requests.request(
"POST",
url,
headers=headers,
data=body
)
sst=response.headers.get('Set-Cookie')
return sst
def query_api(cookie,email):
url="https://reports.domain.com/gdc/account/domains/domain/users?login="+email
body={}
headers={
'Content-Type': 'application/json',
'Accept': 'application/json',
'Cookie': cookie
}
response = requests.request(
"GET",
url,
headers=headers,
data=body
)
jsonContent=[]
jsonContent.append({response.text})
accountSettings=jsonContent[0]
print(accountSettings)
cookie=auth_api(credentials_User,credentials_Password)
profilehash=query_api(cookie,email)
The code itself works and sends a request to the Gooddata API.
The query_api() function returns JSON similar to below
{
"accountSettings": {
"items": [
{
"accountSetting": {
"login": "user#example.com",
"email": "user#example.com",
"firstName": "First Name",
"lastName": "Last Name",
"companyName": "Company Name",
"position": "Data Analyst",
"created": "2020-01-08 15:44:23",
"updated": "2020-01-08 15:44:23",
"timezone": null,
"country": "United States",
"phoneNumber": "(425) 555-1111",
"old_password": "secret$123",
"password": "secret$234",
"verifyPassword": "secret$234",
"authenticationModes": [
"SSO"
],
"ssoProvider": "sso-domain.com",
"language": "en-US",
"ipWhitelist": [
"127.0.0.1"
],
"links": {
"projects": "/gdc/account/profile/{profile_id}/projects",
"self": "/gdc/account/profile/{profile_id}",
"domain": "/gdc/domains/default",
"auditEvents": "/gdc/account/profile/{profile_id}/auditEvents"
},
"effectiveIpWhitelist": "[ 127.0.0.1 ]"
}
}
],
"paging": {
"offset": 20,
"count": 100,
"next": "/gdc/uri?offset=100"
}
}
}
The issue I am having is reading specific keys from this JSON Dict, I can use accountSettings=jsonContent[0] but that just returns the same JSON.
What I want to do is read the value of the project key within links
How would I do this with a dict?
Thanks
Based on your description, uyou have your value inside a list, (not a set. Foergt about set: sets are not used with JSON). Inside your list, you either your content as a single string, which then you'd have to parse with json.loads, or it is simply a well behaved nested data structure already extracted from JSON, but which is inside a single element list. This seems the most likely.
So, you should be able to do:
accountlink = jsonContent[0]["items"][0]["accountSetting"]["login"]
otherwise, if it is encoded as a a json string, you have to parse it first:
import json
accountlink = json.loads(jsonContent[0])["items"][0]["accountSetting"]["login"]
Now, given your question, I'd say your are on a begginer level as a programmer, or a casual user, just using Python to automatize something either way, I'd recommend you do try some exercising before proceeding: it will save you time (a lot of time). I am not trying to bully or mock anything here: this is the best advice I can offer you. Seek for tutorials that play around on the interactive mode, rather than trying entire programs at once that you'd just copy and paste.
Using the below code fixed the issue
jsonContent=json.loads(response.text)
print(type(jsonContent))
test=jsonContent["accountSettings"]["items"][0]
test2=test["accountSetting"]["links"]["self"]
print(test)
print(test2)
I believe this works because for some reason I didn't notice I was using .append for my jsonContent. This resulted in the data type being something other than it should have been.
Thanks to everyone who tried helping me.

How to mock API request used inside function in a Django test?

I've got a little utility function built like this to grab data from another applications API:
# app/utils.py
import json
import requests
from django.conf import settings
def get_future_assignments(user_id):
"""gets a users future assignments list from the API
Arguments:
user_id {int} -- user_id for a User
"""
headers = {
"User-Agent": "Mozilla/5.0",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
}
api_app = settings.ASSIGNMENTS_API_ROOT_URL # http://project.org/appname/
api_model = "futureassignments/"
api_query = "?user_id=" + str(user_id)
json_response = requests.get(
api_app + api_model + api_query, headers=headers, verify=False
)
return json.loads(json_response.content)
It basically builds the API call and returns the response data - I'd like to test this.
# tests/test_utils.py
import mock
from unittest.mock import patch, Mock
from django.test import TestCase
from app.utils import get_future_assignments
class UtilsTest(TestCase):
def setUp(self):
self.futureassignments = [
{
"id": 342,
"user_id": 18888,
"job": 361,
"location": "1234",
"building": "Building One",
"confirmed_at": None,
"returning": None,
"signature": None,
},
{
"id": 342,
"user_id": 18888,
"job": 361,
"location": "1235",
"building": "Building Two",
"confirmed_at": None,
"returning": None,
"signature": None,
},
]
#patch("app.utils.get_future_assignments")
def test_get_future_assignments_with_multi_assignments(self, mock_gfa):
"""
Test for getting future assignments for a user with mocked API
"""
mock_gfa.return_value = Mock()
# set the json response to what we're expecting
mock_gfa.return_value.json.return_value = self.futureassignments
assignments = get_future_assignments(18888)
self.assertEqual(len(assignments), 2)
It keeps giving me an error that it can't reach the API to get a response (which is expected at the moment - since I'm running it locally and it cannot hit the API)
I'm new to using Mock - so maybe I'm way, way off base here.
Any ideas?
Like you, I am also new to using mock. I believe it's intended to work like this:
#patch("requests.get")
def test_get_future_assignments_with_multi_assignments(self, mock_requests_get):
"""
Test for getting future assignments for a user with mocked API
"""
mock_requests_get.return_value = json.dumps(self.futureassignments)
assignments = get_future_assignments(18888)
self.assertEqual(len(assignments), 2)
Please correct me if I'm wrong!

Post GraphQL mutation with Python Requests

I'm having trouble posting mutations with GraphQL and Python Requests.
My function looks like:
def create(request):
access_token = 'REDACTED'
headers = {
"X-Shopify-Storefront-Access-Token": access_token
}
mutation = """
{
checkoutCreate(input: {
lineItems: [{ variantId: "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC80", quantity: 1 }]
}) {
checkout {
id
webUrl
lineItems(first: 5) {
edges {
node {
title
quantity
}
}
}
}
}
}
"""
data = (requests.post('https://catsinuniform.myshopify.com/api/graphql', json={'mutation': mutation}, headers=headers).json())
print(data)
return render(request, 'Stock/create.html', { 'create': data })
I'm getting errors saying I have a bad request "bad_request - Parameter Missing or Invalid" in my json response.
Even though you're sending a mutation, your request body should still include a query property, the value of which should be the string representing your operation. It's a bit confusing, but informally both queries and mutations are called "queries" (you're still "querying" the server either way). Change your request to:
requests.post('https://catsinuniform.myshopify.com/api/graphql', json={'query': mutation}, headers=headers)

python3 flask: get multiple values for key in json post request

I have a simple existing python API using flask that submits a post request in the body, then calls and executes another python script:
testflask.py
import testlogicdf
import json
from flask import Flask, json, request, Response
app = Flask(__name__)
#app.route("/results", methods=['POST'])
def createResults():
entry = request.get_json().get('entry', '')
passcode = request.get_json().get('passcode', '')
data = testlogicdf.test(entry, passcode)
return Response(data, mimetype='application/json')
if __name__ == "__main__":
app.run(debug = True, host='localhost', port=8080, passthrough_errors=False)
script that gets called: testlogicdf.py
import pandas as pd
def passcodeMapping(entry):
result = ''
entry = int(entry)
if (entry in range(1000, 3000)):
result = 'UKNOWN'
elif (entry in range(0, 100)):
result = 'Success'
elif (entry in range(200, 999)):
result = 'Error'
return result
def test(entry, passcode):
df = pd.DataFrame()
testInput = zip(entry, passcode)
for entry, passcode in testInput:
result = passcodeMapping(entry)
df = df.append({'Entry': entry, 'Passcode': passcode, 'Second Attempt': result}, ignore_index=True)
response = df.to_json(orient='records')
return response
To achieve these results:
[
{
"Entry": 2442,
"Passcode": "Restart",
"Second Attempt": "UKNOWN"
},
{
"Entry": 24,
"Passcode": "Try Again",
"Second Attempt": "Success"
},
{
"Entry": 526,
"Passcode": "Proceed",
"Second Attempt": "Error"
}
]
What I am trying to accomplish is instead of passing this in the request body:
{
"entry":[2442, 24, 526],
"passcode":["Restart", "Try Again", "Proceed"]
}
I want to pass this to the API
[{
"entry": "2442",
"passcode": "Restart"
}, {
"entry": "24",
"passcode": "Try Again"
}, {
"entry": "526",
"passcode": "Proceed"
}]
as this is more cleaner and self explanatory. However the issue I am having is when passing that request to my api, I am getting the error "AttributeError: 'list' object has no attribute 'get'"
I've had no luck debugging why I'm not able to pass my request body in that format. Thanks in advance
Your server is trying to get value given a key from the JSON. The JSON you're sending is a list, not a dictionary. You have to either change the JSON you send to be a dictionary and change the server accordingly, or change your server (createResults()) to interpret the JSON as a list and iterate through it.
If you want it to be a dict, you can do something like this:
{
1: {{"Password": "asdf"}, ...},
2: {{"Password": "xzvx"}, ...},
...
}
But a list makes more sense, in my opinion.

List indicies must be integers. not str JSON reponse

I am baffled and do not know how to solve this error. I'm trying to grab every name inside a JSON response list.
My code looks like this.
def extract_strucutres_ids(expected_structures):
response = requests.get(JIRA_REST + "/structures", verify=False)
response = response.json()
for structure in response['structures']:
print structure['name']
The Json reponse looks like this.
{
"structures": [{
"id": 165,
"name": "6.2 External Notifications Refactor",
"description": ""
}, {
"id": 364,
"name": "6.4 Day/Night Mode and Idle Scene Mode",
"description": "",
"readOnly": true
}, {
"id": 140,
"name": "ACC 5 Regression",
"description": ""
}
]
}
I keep getting List indicies must be integers, not str.
Python version 2.7.10
try this -
import json
def extract_strucutres_ids(expected_structures):
response = requests.get(JIRA_REST + "/structures", verify=False)
if response.status_code==200:
response_json = json.loads(response.text)
for structure in response_json['structures']:
print structure['name']
else:
print("Response is {}".format(response.status_code))
Let me know,if it worked!
Use json.loads()
response = requests.get(..)
response = json.loads(response.text) # response.text is a string
for structure in response['structures']:
# Do something

Categories