Flask API optional parameter is not working - api

I have a route that was created via flask_restplus.Api, not flask.Flask.
from flask import Flask
from flask_restplus import Api, Resource
flask_app = Flask(__name__)
app = Api(app=flask_app)
name_space = app.namespace('', description="Описание маршрутизаций")
And I would like to send an optional parameter like this, in the docs. Here is my code to send optional parameter:
from flask_restplus import Resource
#name_space.route("/structure/", defaults={'path': None})
#name_space.route("/structure/<string:path>")
#name_space.doc(params={'path': {'description': 'Get structure of a given path'}})
class struct_level(Resource):
def get(self, path):
print(path) # shows None
return method_to_work()
I've tried to change slashes in the end and to change method to post, nothing helped. Whatever value I send to 'path' parameter it returns None. If I make 'path' parameter required it works well, however I need this parameter to be optional, so that I can pass empty value.
Please, help me with an advice: how to make 'path' parameter optional in a route that was created by Api. Thanks!
P.S: Also, it is needed to be one endpoint.

I realised from my coworkers, that it is impossible to make this request in one route(endpoint). So I just had to create two endpoints, and that was ok.

Related

Insert Record to BigQuery or some RDB during API Call

I am writing a REST API GET endpoint that needs to both return a response and store records to either GCP Cloud SQL (MySQL), but I want the return to not be dependent on completion of the writing of the records. Basically, my code will look like:
def predict():
req = request.json.get("instances")
resp = make_response(req)
write_to_bq(req)
write_to_bq(resp)
return resp
Is there any easy way to do this with Cloud SQL Client Library or something?
Turns our flask has a functionality that does what I require:
#app.route("predict", method=["GET"]):
def predict():
# do some stuff with the request.json object
return jsonify(response)
#app.after_request
def after_request_func(response):
# do anything you want that relies on context of predict()
#response.call_on_close
def persist():
# this will happen after response is sent,
# so even if this function fails, the predict()
# will still get it's response out
write_to_db()
return response
One important thing is that a method tagged with after_request must take an argument and return something of type flask.Response. Also I think if method has call_on_close tag, you cannot access from context of main method, so you need to define anything you want to use from the main method inside the after_request tagged method but outside (above) the call_on_close method.

Unable to pass the value from a variable/JSON file in the payload

I am trying to pass a value inside below payload, I am able to get the value of it from the print but same is not accessible inside the payload, It prints the #(config.Secondary_ED) as the output.
The config.Secondary_ED contains an ip address. It works fine when I give ip address manually.
And print config.Secondary_ED
And request {"agent-forwarding":true,"configuration-data":"{\"service-host\":\"#(config.Secondary_ED)\",\"service-port\":\"8443\",\"user\":\"restdispatcher\",\"protocol\":\"vosrestdispatcher:rest\"}","configuration-template":null,"description":"Change Guardian Default Event Destination sk-12sp5","display-name":"sk-12sp5","ev-prototype-id":"1","forwarding-queries":[""],"id":1,"is-default":true,"is-indelible":true,"method":"vosrestdispatcher:rest","model":"REST Dispatcher","server-fordwarding":false}
When method PUT
Working Payload
#And print config.Secondary_ED
And request {"agent-forwarding":true,"configuration-data":"{\"service-host\":\"1.1.1.1\",\"service-port\":\"8443\",\"user\":\"restdispatcher\",\"protocol\":\"vosrestdispatcher:rest\"}","configuration-template":null,"description":"Change Guardian Default Event Destination sk-12sp5","display-name":"sk-12sp5","ev-prototype-id":"1","forwarding-queries":[""],"id":1,"is-default":true,"is-indelible":true,"method":"vosrestdispatcher:rest","model":"REST Dispatcher","server-fordwarding":false}
**Secondary_ED is stored in a json file called config.js
I have used # many times to get the value but same doesn't work in this case.
Please suggest what did I miss here.
Appreciate your help.
Please notice that the value of configuration-data is a string, not JSON object. Ask a friend who knows JS if this is not clear.
You can try this (note the usage of string):
* string configData = { 'service-host': '#(config.Secondary_ED)' }
* request { foo: '#configData' }
Or just use JS string concatenation (this is just a guess, please figure out what works for you, but you get the idea.
* def configData = '"{\\"service-host\\":\\"' + config.Secondary_ED + '\\"'

How to make a controller on Odoo for custom value?

I need to make a custom controller on Odoo for getting information from the particular task. And I can able to produce the result also. But now I'm facing an issue.
The client needs to retrieve the information with a particular field.
For example,
The client needs to retrieve the information with the tracking number and the data must be JSON format also. If the tracking number is 15556456356, the url should be www.customurl.com/dataset/15556456356
The route of that URL should be #http.route('/dataset/<string:tracking_number>', type='http or json', auth="user or public"), basically the method should be like this:
import json
from odoo import http
from odoo.http import Response, request
class tracking(http.Controller):
# if user must be authenticated use auth="user"
#http.route('/dataset/<string:tracking_number>', type='http', auth="public")
def tracking(self, tracking_number): # use the same variable name
result = # compute the result with the given tracking_number and the result should be a dict to pass it json.dumps
return Response(json.dumps(result), content_type='application/json;charset=utf-8',status=200)
This method accept http request and return a json response, if the client is sending a json requests you should change type='json'. don't forget to import the file in the __init___.py.
Lets take an example let say that I want to return some information about a sale.order by a giving ID in the URL:
import json
from odoo import http
from odoo.http import Response, request
class Tracking(http.Controller):
#http.route('/dataset/<int:sale_id>', type='http', auth="public")
def tracking(self, sale_id):
# get the information using the SUPER USER
result = request.env['sale.order'].sudo().browse([sale_id]).read(['name', 'date_order'])
return Response(json.dumps(result), content_type='application/json;charset=utf-8',status=200)
So when I enter this URL using my Browser: http://localhost:8069/dataset/1:

Jax rs optional header param

I am using dropwizard and jax rs to build my simple webapp. I read that all the query params specified in my method definition are optional and so are the HeaderParams. But here is where I am facing problem.
When I skip passing any query param, still the request is routed to the appropriate method. But when I skip passing header param, my request is not even routed to that method. Kindly help.
Example)
#GET
#Path(/sample)
Public Response getSample(#HeaderParam("header") final String header,
#QueryParam("query") final String query) {
}
In this sample, if I call this method with "header", this method gets invoked irrespective of whether I pass "query" param or not. At the same time, if I don't pass the "header", this method is not even getting invoked.
Also even if I give curl -H "header:" "http://localhost/sample?query=dummy" the request is not getting routed. I have to necessarily give a value for my header. Kindly help.
Note: I wrote down simplified representation of my code. Internally I am using dropwizard and swagger.
Thanks,
Sriram

Django-Rest-Framework: How to Document GET-less Endpoint?

My co-worker implemented an API that only allows GET requests with an ID parameter (so I can GET /foo/5 but can't GET /foo/). If I try to access the API's endpoint without providing an ID parameter, it (correctly) throws an unimplemented exception.
I want to fix this endpoint to show its documentation when viewed, without an ID, over the web. However, I still want it to throw an exception when that endpoint is accessed programatically.
As I remember it, django-rest-framework is capable of distinguishing those two cases (via request headers), but I'm not sure how to define the endpoint such that it returns either documentation HTML or an exception as appropriate.
Can anyone help provide the pattern for this?
Based on the description, I would guess that the endpoint is a function based view, which is registered on a route where it listens for get requests WITH parameters. I would suggest to register another route where you will listen for get requests without parameters...
from rest_framework.decorators import api_view
from rest_framework import status
#api_view(['GET'])
def existing_get_item_api(request, item_id, *args, **kwargs):
# query and return the item here ...
pass
#api_view(['GET'])
def get_help(request, *args, **kwargs):
# compose the help
return Response(data=help, status = status.HTTP_200_OK)
# somewhere in urls.py
urlpatterns = [
url(r'api/items/(?P<item_id>[0-9]+)/', existing_get_item_api),
url(r'api/items/', get_help),
]
Let me know how is this working out for you.
We can user modelviewsets and routers for this implementation
viewsets.py
class AccountViewSet(viewsets.ModelViewSet):
"""
A simple ViewSet for viewing and editing accounts.
"""
http_method_names = ['GET']
queryset = Account.objects.all()
serializer_class = AccountSerializer
routers.py
from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'accounts', AccountViewSet)