Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use 'form' location and process request as json? #594

Open
sandyboxy opened this issue Feb 7, 2024 · 6 comments
Open

How to use 'form' location and process request as json? #594

sandyboxy opened this issue Feb 7, 2024 · 6 comments
Labels
question Further information is requested

Comments

@sandyboxy
Copy link

Ask a question
How to use 'form' location and process request as json?

Additional context
I wish to use form field to allow users to test my API by filling field instead of to fill a raw JSON dict.
This is my relevant code:

parser = api.parser()
parser.add_argument('title', type=str, help='Some param', required=True, location=('form', 'json'))
parser.add_argument('content', type=str, help='Some param',  required=True, location=('form', 'json'))

@api.route('/send')
class Send(Resource):
    @api.doc(parser=parser, validate=True)
    def post(self, **kwargs):
        print(request.args.get('title'))   # it prints title
        print(request.json) # it fails

when I set field location='form' I have the form with fields to fill but the request is

curl -X 'POST' \
  'http://localhost:5000/send?title=test&content=test' \
  -H 'accept: application/json' \
  -d ''

but I wish to have the following output without to set location='json'

curl -X 'POST' \
  'http://localhost:5000/send' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "title",
  "content": "content",
}'
@sandyboxy sandyboxy added the question Further information is requested label Feb 7, 2024
@peter-doggart
Copy link
Contributor

peter-doggart commented Feb 7, 2024

Flask puts form data in a different place in the Request object. You need to call request.form to get form data directly. As you see, request.json will be empty or not set in the case that only form data is passed.

However, you have set up a request parser here but you don't currently use it. So you should be able to use it to retrieve the values regardless of location passed to your code. Something like:

parser = api.parser()
parser.add_argument('title', type=str, help='Some param', required=True, location=('form', 'json'))
parser.add_argument('content', type=str, help='Some param',  required=True, location=('form', 'json'))

@api.route('/send')
class Send(Resource):
    @api.doc(parser=parser, validate=True)
    def post(self, **kwargs):
        input_args = parser.parse_args() # This returns a dictionary containing the parsed values from the specified locations.
        print(f"Title: {input_args['title']}")
        print(f"Content: {input_args['content']}")

@sandyboxy
Copy link
Author

So, if I use location=('form', 'json')

  • a POST request with empty data is call (see picture below);
  • params are passed in URL request instead of body

flask

This is the output I wish to have:

CURL

curl -X 'POST' \
  'http://localhost:5000/send \
  -H 'accept: application/json' \
  -d '{"title":"test", "content":"test"}'

Request URL

http://localhost:5000/send

I know I can have this by set location='json' but, as I said, in this way I would not have a form with input fields.

@kartikeyporwal
Copy link

So, if I use location=('form', 'json')

  • a POST request with empty data is call (see picture below);
  • params are passed in URL request instead of body

flask

This is the output I wish to have:

CURL

curl -X 'POST' \
  'http://localhost:5000/send \
  -H 'accept: application/json' \
  -d '{"title":"test", "content":"test"}'

Request URL

http://localhost:5000/send

I know I can have this by set location='json' but, as I said, in this way I would not have a form with input fields.

@sandyboxy, try with location="form"

@sandyboxy
Copy link
Author

@sandyboxy, try with location="form"

Hi @kartikeyporwal,
if I try with location="form" setting I obtain the following output:

curl -X 'POST' \
  'http://localhost:5000/send' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'title=test&content=test'

instead of having the following:

curl -X 'POST' \
  'http://localhost:5000/send' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "string",
  "content": "string"
}'

@kartikeyporwal
Copy link

@sandyboxy, try with location="form"

Hi @kartikeyporwal, if I try with location="form" setting I obtain the following output:

curl -X 'POST' \
  'http://localhost:5000/send' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'title=test&content=test'

instead of having the following:

curl -X 'POST' \
  'http://localhost:5000/send' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "string",
  "content": "string"
}'

Why you need the json when you are specifying the params as form? If you need to pass json then specify location="json".

  • If you specify in location=json, send data in json and receive data as json using request.json
  • If you specify in location=form, send data in form and receive data as form using request.form

@sandyboxy
Copy link
Author

Simply I wish to use swagger/flask-api to show a simplified page to test API (using form view) and show output as json output instead of form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants