Python Falcon filtering through URL - python

I have a small API that i'm working on, everything works ok, all my requests do what they are supposed to but when I try to filter results through the URL query for some reason it works for id but not for device field.
def on_get(self, req, resp):
"""Handles GET requests"""
if req.get_param("id"):
result = {'location': r.db(PROJECT_DB).table(PROJECT_TABLE).get(req.get_param("id")).run(db_connection)}
elif req.get_param("device"):
result = {'location': r.db(PROJECT_DB).table(PROJECT_TABLE).get(req.get_param("device")).run(db_connection)}
else:
location = r.db(PROJECT_DB).table(PROJECT_TABLE).run(db_connection)
result = {'locations': [i for i in location]}
resp.body = json.dumps(result)
example http://localhost:8000/location?id=(some random id) this will work
but if i do http://localhost:8000/location?device=(some device) this will not work, returns null
So could anyone tell me what am I doing wrong? or better yet if anyone knows a better way to filter using the URL?
Note: I am using rethinkdb
EDIT:
This is what I have normally:
{
"locations": [
{
"id": "4bf4b94f-747a-42db-9d54-a8399d995025",
"location": "gps coords",
"device": "Device 2"
},
{
"id": "b5cce561-37d2-42e7-86e4-a31c008b0af2",
"location": "gps coords",
"device": "Device 1"
},
{
"id": "bebba7cf-710c-4ee8-ad69-2d58174d4e02",
"location": "gps coords",
"device": "Device 1"
},
{
"id": "e928f84b-60ff-40f3-b839-920bc99e5480",
"location": "gps coords",
"device": "Device1"
}
]
}
Filtering by id works ok, but not by device which is weird

I found the answer to this problem, the reason why it did not war was because rethinkdb only gets via primary key on the get query
result = {'location': r.db(PROJECT_DB).table(PROJECT_TABLE).get(req.get_param("device")).run(db_connection)}
so what I should have done was to filter the results by what I wanted like this and it would have worked
result = {'location': list(r.db(PROJECT_DB).table(PROJECT_TABLE).filter({'device': param}).run(db_connection))}
Thanks for the help everyone and hope this answer helps.

Related

How to parse nested JSON object?

I am working on a new project in HubSpot that returns nested JSON like the sample below. I am trying to access the associated contacts id, but am struggling to reference it correctly (the id I am looking for is the value '201' in the example below). I've put together this script, but this script only returns the entire associations portion of the JSON and I only want the id. How do I reference the id correctly?
Here is the output from the script:
{'contacts': {'paging': None, 'results': [{'id': '201', 'type': 'ticket_to_contact'}]}}
And here is the script I put together:
import hubspot
from pprint import pprint
client = hubspot.Client.create(api_key="API_KEY")
try:
api_response = client.crm.tickets.basic_api.get_page(limit=2, associations=["contacts"], archived=False)
for x in range(2):
pprint(api_response.results[x].associations)
except ApiException as e:
print("Exception when calling basic_api->get_page: %s\n" % e)
Here is what the full JSON looks like ('contacts' property shortened for readability):
{
"results": [
{
"id": "34018123",
"properties": {
"content": "Hi xxxxx,\r\n\r\nCan you clarify on how the blocking of script happens? Is it because of any CSP (or) the script will decide run time for every URL’s getting triggered from browser?\r\n\r\nRegards,\r\nLogan",
"createdate": "2019-07-03T04:20:12.366Z",
"hs_lastmodifieddate": "2020-12-09T01:16:12.974Z",
"hs_object_id": "34018123",
"hs_pipeline": "0",
"hs_pipeline_stage": "4",
"hs_ticket_category": null,
"hs_ticket_priority": null,
"subject": "RE: call followup"
},
"createdAt": "2019-07-03T04:20:12.366Z",
"updatedAt": "2020-12-09T01:16:12.974Z",
"archived": false
},
{
"id": "34018892",
"properties": {
"content": "Hi Guys,\r\n\r\nI see that we were placed back on the staging and then removed again.",
"createdate": "2019-07-03T07:59:10.606Z",
"hs_lastmodifieddate": "2021-12-17T09:04:46.316Z",
"hs_object_id": "34018892",
"hs_pipeline": "0",
"hs_pipeline_stage": "3",
"hs_ticket_category": null,
"hs_ticket_priority": null,
"subject": "Re: Issue due to server"
},
"createdAt": "2019-07-03T07:59:10.606Z",
"updatedAt": "2021-12-17T09:04:46.316Z",
"archived": false,
"associations": {
"contacts": {
"results": [
{
"id": "201",
"type": "ticket_to_contact"
}
]
}
}
}
],
"paging": {
"next": {
"after": "35406270",
"link": "https://api.hubapi.com/crm/v3/objects/tickets?associations=contacts&archived=false&hs_static_app=developer-docs-ui&limit=2&after=35406270&hs_static_app_version=1.3488"
}
}
}
You can do api_response.results[x].associations["contacts"]["results"][0]["id"].
Sorted this out, posting in case anyone else is struggling with the response from the HubSpot v3 Api. The response schema for this call is:
Response schema type: Object
String results[].id
Object results[].properties
String results[].createdAt
String results[].updatedAt
Boolean results[].archived
String results[].archivedAt
Object results[].associations
Object paging
Object paging.next
String paging.next.after
String paging.next.linkResponse schema type: Object
String results[].id
Object results[].properties
String results[].createdAt
String results[].updatedAt
Boolean results[].archived
String results[].archivedAt
Object results[].associations
Object paging
Object paging.next
String paging.next.after
String paging.next.link
So to access the id of the contact associated with the ticket, you need to reference it using this notation:
api_response.results[1].associations["contacts"].results[0].id
notes:
results[x] - reference the result in the index
associations["contacts"] -
associations is a dictionary object, you can access the contacts item
by it's name
associations["contacts"].results is a list - reference
by the index []
id - is a string
In my case type was ModelProperty or CollectionResponseProperty couldn't reach dict anyhow.
For the record this got me to go through the results.
for result in list(api_response.results):
ID = result.id

Flask-restplus returning marshal model instead of the data

So I'm pretty new to implementing flask-restplus and I have encountered this road block.
I have read the restplus docs over and over again and followed several exampled. But the behavior that I'm facing is very much different from what is supposed to be.
So I have a model that is supposed to be a list of objects of another model (returned from the function drone_model()).
drones_list = api.model('drones_list', {
'items': fields.List(fields.Nested(drone_model())),
'message':fields.String(''),
'code': fields.Integer('')
})
Everything works fine, no errors. But when I try the API (http://127.0.0.1:5000/datamine/v2/drones), as a response I get the Marshalling model back instead of the data itself. If I print the data, it gets printed, but for some reason in the web, the restplus model is returned.
Below I have the code that I had written. If I take the marshal_with decorator off, then the data is returned just fine.
#api.route('/')
class DronesList(Resource):
#api.marshal_with(drones_list, envelope='data')
#api.response(200, 'All drones successfully fetched!')
def get(self):
"""
Get all drones!.
"""
from app.utils.common import get_start_end_date_from_request
start_date, end_date = get_start_end_date_from_request(request)
drones = []
for drone in Drone.objects:
drones.append({
'id': str(drone.id),
'serial_id': drone.serial_id,
'maintenances': [],
'status': get_dynamic_status(drone, start_date, end_date),
'picture_url': drone.asset.picture_url,
'manufacturer': drone.asset.manufacturer,
'model_name': drone.asset.model_name,
'drone_type': drone.asset.drone_type,
'payload_type': drone.asset.payload_type,
'asset_url': drone.get_url(drone.id)
})
success = ClientSuccessFunctionClass('All drones successfully fetched!', 200, drones)
return (success.to_dict())
These are the outputs on the browser:
1. Without the marshal decorator:
{
"data": {
"items": [
{
"id": "5aeafcb93a33683f73827e91",
"serial_id": "Drone 1",
"maintenances": [],
"status": "Decommissioned",
"picture_url": "some img url",
"manufacturer": "DJI",
"model_name": "Phantom 4 Pro",
"drone_type": "Quadcopter",
"payload_type": "RGB Camera",
"asset_url": "http://127.0.0.1:5000/datamine/v1/drones/5aeafcb93a33683f73827e91"
},
{
"id": "5aeaff374f85747f90df2714",
"serial_id": "Drone 2",
"maintenances": [],
"status": "Available",
"picture_url": "sime url",
"manufacturer": "DJI",
"model_name": "Phantom 4",
"drone_type": "Quadcopter",
"payload_type": "RGB Camera",
"asset_url": "http://127.0.0.1:5000/datamine/v1/drones/5aeaff374f85747f90df2714"
}
],
"message": "All drones successfully fetched!",
"code":200
}
}
2. With the marshal decorator:
{
"data": {
"items": [
{
"id": "Id of Drone",
"serial_id": "Name of Drone",
"status": "Status of Drone",
"maintenances": null,
"picture_url": "Picture URL",
"manufacturer": "Manufacturer of Drone",
"model_name": "Model name of Drone",
"drone_type": "Type of Drone",
"payload_type": "Payload type of Drone",
"asset_url": "Asset URL of Drone"
}
],
"message": "",
"code": ""
}
}
It would be really helpful if someone could tell me what I'm doing wrong as I need to recive the output as the one shown in snippet of the output without the decorator.
Thank you.
Here is a diagram showing invocation order from top to bottom to help make sense of what is happening:
get()
→ api.response(200, 'All drones successfully fetched!') # documents the response
→ api.marshal_with(drones_list, envelope='data')` # returns marshalled dict
The result from invoking get is passed to the api.response decorator function whose result is passed on to api.marshal_with decorator function.
Looking at the shape of the dictionary returned from invoking get()
{
data {
items [
{
id,
serial_id,
maintenances,
status,
picture_url,
manufacturer,
model_name,
drone_type,
payload_type,
asset_url
}
],
message,
code
}
}
The message and code in the response are nested inside of the data.
You need to model the data appropriately, to be able to marshal it. This can be done by passing an argument for what field to look up in the marshal dictionary.
drones_list = api.model('drones_list', {
'items': fields.List(fields.Nested(drone_model()), attribute='data.items'),
'message':fields.String(attribute='data.message'),
'code': fields.Integer(attribute='data.code')
})
As you can see, it's pretty redundant applying the api.marshal_with decorator function on the view given that it's only unnests then nests the result in data field.

Issue in updating elastic search field

This how my result source looks like.
{"_source": {"Name": "Where's My Crown Angry birds 3","movie_id":69}}
I need to update the Name field as "'Where's My Crown'". I used the following query:
{"script": {"inline": "ctx._source.Name='Where's My Crown'","lang": "painless"},"query": {"match": {"movie_id": 69}}}
But I got this error:
{'type': 'illegal_argument_exception', 'reason': "unexpected token ['s'] was expecting one of [{<EOF>, ';'}]."}**
Please help me to fix this.
This is because of the fact that there is a single quote in "Where's My Crown" and that interferes with the single quotes around the whole string.
Consider doing it like this (using params) instead:
{
"script": {
"inline": "ctx._source.Name = params.newName",
"params": {
"newName": "Where's My Crown"
},
"lang": "painless"
},
"query": {"match": {"movie_id": 69}}
}
I tried the solution below and it also worked for me:
Replace
'Where's My Crown'
with
\"Where's My Crown\"
So in my case (in JavaScript, not Python, but I think it would work similarly):
const script = Object.entries(newBody).reduce((prev, [key, value]) => {
return `${prev} ctx._source.${key}=\"${value}\";`;
}, '');

Robinhood API Python

I'm having something strange happen with the Robinhood API. Specifically with getting all of the options instruments (just data about the options). The code below is part of my program
def get_options_instruments(self):
params = {
"chain_symbol" : "AMD",
"chain_id" : "e66ce029-db96-4572-87a0-b144613c08bf",
"type": "call",
"state": "active",
"tradability": "tradable",
"strike_price" : "16.0000",
"expiration_date": "2018-10-19"
}
#API_URLS['option-instrument']= "https://api.robinhood.com/options/instruments/"
response = self.login_session.get(API_URLS['option-instrument'],params = params)
response = response.json()["results"]
print(json.dumps(response,indent = 4,separators=(',', ': ')))#'option-instrument' : "https://api.robinhood.com/options/instruments/",
All parameters seem to have an effect when receiving the option instruments EXCEPT expiration date (which is the most one of the important parameters that I need to use). Below is a sample response of an option instrument.
{
"issue_date": "1987-01-12",
"strike_price": "16.0000",
"url": "https://api.robinhood.com/options/instruments/3cb75cca-0987-46d7-bff1-20cadfb74a83/",
"expiration_date": "2018-07-20",
"tradability": "tradable",
"chain_id": "e66ce029-db96-4572-87a0-b144613c08bf",
"updated_at": "2018-06-03T00:16:56.985489Z",
"min_ticks": {
"cutoff_price": "3.00",
"below_tick": "0.01",
"above_tick": "0.05"
},
"state": "active",
"id": "3cb75cca-0987-46d7-bff1-20cadfb74a83",
"chain_symbol": "AMD",
"type": "call",
"created_at": "2017-11-18T04:15:17.795113Z"
}
I'm just wondering if anybody has any idea why something like this might happen? Could it perhaps be something on the API's side and not mine? Thank you.
Use "expiration_dates" instead and it will work.
I encountered this issue recently as well, where specifying parameters for the "expiration_date" field yielded nothing.

Accessing nested objects with python

I have a response that I receive from foursquare in the form of json. I have tried to access the certain parts of the object but have had no success. How would I access say the address of the object? Here is my code that I have tried.
url = 'https://api.foursquare.com/v2/venues/explore'
params = dict(client_id=foursquare_client_id,
client_secret=foursquare_client_secret,
v='20170801', ll=''+lat+','+long+'',
query=mealType, limit=100)
resp = requests.get(url=url, params=params)
data = json.loads(resp.text)
msg = '{} {}'.format("Restaurant Address: ",
data['response']['groups'][0]['items'][0]['venue']['location']['address'])
print(msg)
Here is an example of json response:
"items": [
{
"reasons": {
"count": 0,
"items": [
{
"summary": "This spot is popular",
"type": "general",
"reasonName": "globalInteractionReason"
}
]
},
"venue": {
"id": "412d2800f964a520df0c1fe3",
"name": "Central Park",
"contact": {
"phone": "2123106600",
"formattedPhone": "(212) 310-6600",
"twitter": "centralparknyc",
"instagram": "centralparknyc",
"facebook": "37965424481",
"facebookUsername": "centralparknyc",
"facebookName": "Central Park"
},
"location": {
"address": "59th St to 110th St",
"crossStreet": "5th Ave to Central Park West",
"lat": 40.78408342593807,
"lng": -73.96485328674316,
"labeledLatLngs": [
{
"label": "display",
"lat": 40.78408342593807,
"lng": -73.96485328674316
}
],
the full response can be found here
Like so
addrs=data['items'][2]['location']['address']
Your code (at least as far as loading and accessing the object) looks correct to me. I loaded the json from a file (since I don't have your foursquare id) and it worked fine. You are correctly using object/dictionary keys and array positions to navigate to what you want. However, you mispelled "address" in the line where you drill down to the data. Adding the missing 'a' made it work. I'm also correcting the typo in the URL you posted.
I answered this assuming that the example JSON you linked to is what is stored in data. If that isn't the case, a relatively easy way to see exact what python has stored in data is to import pprint and use it like so: pprint.pprint(data).
You could also start an interactive python shell by running the program with the -i switch and examine the variable yourself.
data["items"][2]["location"]["address"]
This will access the address for you.
You can go to any level of nesting by using integer index in case of an array and string index in case of a dict.
Like in your case items is an array
#items[int index]
items[0]
Now items[0] is a dictionary so we access by string indexes
item[0]['location']
Now again its an object s we use string index
item[0]['location']['address]

Categories