Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have an odd behavior for one of my endpoints in my Flask application which accepts boolean query parameters. No matter what I pass to it, such as asfsdfd or true or false, it is considered true. Only by leaving it empty does it become false.

full_info = request.args.get("fullInfo", default=False, type=bool)
if full_info:
    # do stuff

It seems to be that either any input is considered to be true. Is there any way to make this work with the Flask intended way of defining the type, or do I need to accept a string and compare it?

like image 267
Curunir Avatar asked Jan 05 '21 08:01

Curunir


People also ask

How do you change true to false in Python?

You can convert True and False to strings 'True' and 'False' with str() . Non-empty strings are considered True , so if you convert False to strings with str() and then back to bool type with bool() , it will be True .

How do you request parameters on a flask?

In the first one we would use request. args. get('<argument name>') where request is the instance of the class request imported from Flask. Args is the module under which the module GET is present which will enable the retrieve of the parameters.

How do you convert a Boolean to a string in Python?

Python convert boolean to string To convert boolean to string in python, we will use str(bool) and then it will be converted to string.


3 Answers

The type parameter of request.args.get is a bit misleading, as it's 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 unfortunately, 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):

full_info = request.args.get('fullInfo', default=False, type=lambda v: v.lower() == '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}
like image 172
Gino Mempin Avatar answered Oct 21 '22 00:10

Gino Mempin


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'

like image 5
Vito De Tullio Avatar answered Oct 21 '22 00:10

Vito De Tullio


This is expected as query string is an actual string, hence when you get a string no matter what it is, if it's not empty, it will be true. As in:

>>>bool('False')
True

You will have to do string comparison if you want to get a boolean.

like image 3
dmitrybelyakov Avatar answered Oct 20 '22 23:10

dmitrybelyakov