Search code examples
pythonpython-3.xpostflaskget

Flask: use [GET, POST] function for a single URL


I'm new to Flask and wondering if it is possible to use the same URL to display a form in html and query to display something

Ideally, I want to have the following result to happen.

If I'm going to create a query inside 138.10.2.1/sample by doing this:

http://138.10.2.1:8000/sample?psi=1&lavr=1&dsc=1&ifsc=1&ics=1&eng=3&ol1=1&ol2=1&reso=1&educ=1&listen=1&time=1&probe=1&unders=1

It will display:

*something in json format*

in the webpage

Else, if I'll just go straight to this:

http://138.10.2.1:8000/sample

It will direct me to a .html page with a form to fill or allow a user to attach a file to use and upload to display a transformed file in json format also.

Here's my code

sample.py

from flask import Flask, flash, request, redirect, url_for, make_response, send_from_directory, render_template
import convert as ps

app = Flask(__name__)

@app.route("/sample", methods=["GET", "POST"])
def query_strings():

    #This is not working: if request.method == "POST":

        args1 = request.args["psi"]
        args2 = request.args["lavr"]
        args3 = request.args["dsc"]
        args4 = request.args["ifsc"]
        args5 = request.args["ics"]
        args6 = request.args["eng"]
        args7 = request.args["ol1"]
        args8 = request.args["ol2"]
        args9 = request.args["reso"]
        args10 = request.args["educ"]
        args11 = request.args["listen"]
        args12 = request.args["time"]
        args13 = request.args["probe"]
        args14 = request.args["unders"]

        args_list = [args1, args2, args3, args4, args5, args6, args7, args8,args9, args10, args11, args12, args13, args14]


        result = ps.execute(args_list)
        response = app.response_class(
            response=result,
            status=200,
            mimetype='application/json'
        )
        return response
    #This is my html form: return render_template("form.html")
if __name__ == '__main__':
   app.run(debug = True)

Right now, what I can have is to run the query but I am getting prompted to enter the paramaters I declared if I just entered:

http://138.10.2.1:8000/sample

Solution

  • You can check the number of arguments and return the HTML form if the length is 0 like this:

        # if there are no arguments provided, show HTML form
        if len(request.args) == 0:
            return render_template("form.html")
    

    Also, there's no need to store each argument as a separate variable and then combine them into a list. request.args is already a dictionary so you can simply get a list of the argument names and values with:

    list(request.args.keys()) # list of argument names eg. ['psi', 'lavr', 'dsc', 'ifsc'...]
    list(request.args.values()) # list of argument values eg. [1, 1, 1, 1...]
    

    You can check if the argument names match a desired set:

    if set(argument_names) == {"psi","lavr","dsc","ifsc","ics","eng","ol1","ol2","reso","educ","listen","time","probe","unders"}:
            # return JSON
    

    Overall, your code could look something like this:

    from flask import Flask, request, render_template
    import json
    
    app = Flask(__name__)
    
    @app.route("/sample", methods=["GET", "POST"])
    def query_strings():
        # if there are no arguments provided, show HTML form
        if len(request.args) == 0:
            return render_template("form.html")
    
        argument_names = list(request.args.keys())
    
        # if the argument list is valid
        if set(argument_names) == {"psi","lavr","dsc","ifsc","ics","eng","ol1","ol2","reso","educ","listen","time","probe","unders"}:
            # return JSON
            response = app.response_class(
                    response=json.dumps(request.args),
                    status=200,
                    mimetype='application/json'
            )
            return response
    
        return "Invalid arguments"
    
    if __name__ == '__main__':
        app.run(debug = True)
    

    This will:

    • show form.html if you load /sample with no arguments
    • show the arguments as JSON if you load /sample with valid arguments (eg. /sample?psi=1&lavr=1&dsc=1&ifsc=1&ics=1&eng=3&ol1=1&ol2=1&reso=1&educ=1&listen=1&time=1&probe=1&unders=1)
    • show "Invalid arguments" in any other case