How to pass a parameter from client side to server in python

Question:

I am using flask and flask-restx try to create a protocol to get a specific string from another service. I am wonder if there is a way I can pass the parameter from another function to server side.
For example, here’s my server side:

from flask_restx import Api,fields,Resource
from flask import Flask
app = Flask(__name__)
api = Api(app)

parent = api.model('Parent', {
    'name': fields.String(get_answer(a,b)),
    'class': fields.String(discriminator=True)
})
@api.route('/language')
class Language(Resource):
    # @api.marshal_with(data_stream_request)
    @api.marshal_with(parent)
    @api.response(403, "Unauthorized")
    def get(self):

        return {"happy": "good"}

get_answer function in a different file:

get_answer(a,b):
  return a + b

What I expect is to get the result of get_answer from a file, and then my API is generated so that the GET request can get it. I know that if there is a web page, we can use render_template( or form to get it. But what if I want to get the value from another function? I know we only run the server with app.run(), but are we able to pass any value into the server? Guessing app.run(a,b) should not work in this case. We definite need to pass two parameter into the server. Or we can store the answer of get_answer(a,b) in main with specific value of a and b, then pass the number into the server side. But it will need the parameter either way.


One thing I’ve tested is wrapping up the server into a function. But in our case, is it a good idea to wrap a class inside a function as we have class Language(Resource):?

Asked By: Youkijiudai

||

Answers:

You can use request parameters or the request body to pass in data to your endpoints. For example, you could define your endpoint like this:

@api.route('/language')
class Language(Resource):
    @api.marshal_with(parent)
    @api.response(403, "Unauthorized")
    def get(self):
        a = request.args.get('a')
        b = request.args.get('b')
        result = get_answer(a, b)
        return {"result": result}

In this example, you can call the endpoint with a query string like this: /language?a=1&b=2 and the get_answer() function will be called with a=1 and b=2.

Alternatively, you could use the request body to pass in the data, like this:

@api.route('/language')
class Language(Resource):
    @api.expect(parent)
    @api.response(403, "Unauthorized")
    def post(self):
        data = request.get_json()
        a = data['a']
        b = data['b']
        result = get_answer(a, b)
        return {"result": result}

In this case, you would call the endpoint with a POST request and include a JSON object in the request body with the values for a and b.

As for your question about wrapping your Flask app in a function, this is generally not recommended. Flask is designed to be run as a standalone web application, and wrapping it in a function can cause issues with how Flask manages its internal state.

It is better to define your Flask app and its endpoints in the global scope, and then run the app with app.run() when you are ready to start the server. (just sharing my opinion)

If you still want to do this, you can define a function that creates and runs a Flask app like this:

def create_app():
    app = Flask(__name__)
    api = Api(app)

    parent = api.model('Parent', {
        'name': fields.String(get_answer(a,b)),
        'class': fields.String(discriminator=True)
    })

    @api.route('/language')
    class Language(Resource):
        # @api.marshal_with(data_stream_request)
        @api.marshal_with(parent)
        @api.response(403, "Unauthorized")
        def get(self):
            return {"happy": "good"}

    return app

You can then call this function to create your Flask app and run it like this:

app = create_app()
app.run()
Answered By: haggbart

get_answer function in a different file

Then import and call it

from other_file import get_answer

... 
def get(self):
    return {"answer": get_answer(2,2)}

As the other answer shows, if you want to use custom arguments, parse them from the request object

Answered By: OneCricketeer