The Python Oracle

Why does the Flask bool query parameter always evaluate to true?

This video explains
Why does the Flask bool query parameter always evaluate to true?

--

Become part of the top 3% of the developers by applying to Toptal
https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Techno Intrigue Looping

--

Chapters
00:00 Question
00:47 Accepted answer (Score 3)
01:12 Answer 2 (Score 26)
02:55 Answer 3 (Score 5)
03:14 Answer 4 (Score 0)
03:33 Thank you

--

Full question
https://stackoverflow.com/questions/6557...

Answer 1 links:
[request.args.get]: https://werkzeug.palletsprojects.com/en/...

Answer 3 links:
[https://github.com/noirbizarre/flask-res...]: https://github.com/noirbizarre/flask-res...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #python3x #flask

#avk47



ACCEPTED ANSWER

Score 47


The type parameter of request.args.get is not for specifying the value's type, but for specifying a callable:

  • type – A callable that is used to cast the value in the MultiDict. If a ValueError is raised by this callable the default value is returned.

It accepts a callable (ex. a function), applies that callable to the query parameter value, and returns the result. So the code

request.args.get("fullInfo", default=False, type=bool)

calls bool(value) where value is the query parameter value. In Flask, the query parameter values are always stored as strings. And calling bool() on a non-empty string will always be True:

In [10]: bool('true')
Out[10]: True

In [11]: bool('false')
Out[11]: True

In [12]: bool('any non-empty will be true')
Out[12]: True

In [13]: bool('')
Out[13]: False

Instead of bool, you can pass a function that explicitly checks if the string is equal to the literal string true (or whichever value your API rules consider as true-ish):

def is_it_true(value):
  return value.lower() == 'true'

@app.route("/test")
def test():
  full_info = request.args.get('fullInfo', default=False, type=is_it_true)
  return jsonify({'full_info': full_info})
$ curl -XGET http://localhost:5000/test?fullInfo=false
{"full_info":false}

$ curl -XGET http://localhost:5000/test?fullInfo=adasdasd
{"full_info":false}

$ curl -XGET http://localhost:5000/test?fullInfo=11431423
{"full_info":false}

$ curl -XGET http://localhost:5000/test?fullInfo=
{"full_info":false}

$ curl -XGET http://localhost:5000/test?fullInfo=true
{"full_info":true}

$ curl -XGET http://localhost:5000/test?fullInfo=TRUE
{"full_info":true}

$ curl -XGET http://localhost:5000/test
{"full_info":false}



ANSWER 2

Score 7


A "trick" is to use json.loads as type. It will act as a "factory" that will build a bool True/False from the strings 'true'/'false'




ANSWER 3

Score 1


It would work properly if you use flask_restplus.inputs.boolean type instead of bool. It's explained here. https://github.com/noirbizarre/flask-restplus/issues/199#issuecomment-276645303