New implementation for RequestParams

- no longer subclasses dict
- request.args[key] now returns first item, not all items
- removed request.raw_args entirely

Closes #774
pull/783/head
Simon Willison 2020-05-29 16:18:01 -07:00
rodzic f272cbc65f
commit 81be31322a
6 zmienionych plików z 49 dodań i 16 usunięć

Wyświetl plik

@ -32,7 +32,7 @@ def json_renderer(args, data, view_name):
# Handle the _json= parameter which may modify data["rows"]
json_cols = []
if "_json" in args:
json_cols = args["_json"]
json_cols = args.getlist("_json")
if json_cols and "rows" in data and "columns" in data:
data["rows"] = convert_specific_columns_to_json(
data["rows"], data["columns"], json_cols

Wyświetl plik

@ -753,17 +753,41 @@ def escape_fts(query):
)
class RequestParameters(dict):
class RequestParameters:
def __init__(self, data):
# data is a dictionary of key => [list, of, values]
assert isinstance(data, dict), "data should be a dictionary of key => [list]"
for key in data:
assert isinstance(
data[key], list
), "data should be a dictionary of key => [list]"
self._data = data
def __contains__(self, key):
return key in self._data
def __getitem__(self, key):
return self._data[key][0]
def keys(self):
return self._data.keys()
def __iter__(self):
yield from self._data.keys()
def __len__(self):
return len(self._data)
def get(self, name, default=None):
"Return first value in the list, if available"
try:
return super().get(name)[0]
return self._data.get(name)[0]
except (KeyError, TypeError):
return default
def getlist(self, name):
"Return full list"
return super().get(name) or []
return self._data.get(name) or []
class ConnectionProblem(Exception):

Wyświetl plik

@ -63,11 +63,6 @@ class Request:
def args(self):
return RequestParameters(parse_qs(qs=self.query_string))
@property
def raw_args(self):
# Deprecated, undocumented - may be removed in Datasette 1.0
return {key: value[0] for key, value in self.args.items()}
async def post_vars(self):
body = []
body = b""

Wyświetl plik

@ -277,11 +277,11 @@ class TableView(RowTableShared):
# it can still be queried using ?_col__exact=blah
special_args = {}
other_args = []
for key, value in args.items():
for key in args:
if key.startswith("_") and "__" not in key:
special_args[key] = value[0]
special_args[key] = args[key]
else:
for v in value:
for v in args.getlist(key):
other_args.append((key, v))
# Handle ?_filter_column and redirect, if present

Wyświetl plik

@ -268,12 +268,16 @@ The object also has one awaitable method:
The RequestParameters class
---------------------------
This class, returned by ``request.args``, is a subclass of a Python dictionary that provides methods for working with keys that map to lists of values.
This class, returned by ``request.args``, is a dictionary-like object.
Conider the querystring ``?foo=1&foo=2``. This will produce a ``request.args`` that looks like this::
Consider the querystring ``?foo=1&foo=2``. This will produce a ``request.args`` that looks like this::
RequestParameters({"foo": ["1", "2"]})
Calling ``request.args.get("foo")`` will return the first value, ``"1"``. If that key is not present it will return ``None`` - or the second argument if you passed one, which will be used as the default.
``request.args["foo"]`` returns the first value, ``"1"`` - or raises ``KeyError`` if that key is missing.
Calling ``request.args.getlist("foo")`` will return the full list, ``["1", "2"]``. If you call it on a missing key it will return ``[]``.
``request.args.get("foo")`` returns ``"1"`` - or ``None`` if the key is missing. A second argument can be used to specify a different default value.
``request.args.getlist("foo")`` returns the full list, ``["1", "2"]``. If you call it on a missing key it will return ``[]``.
You can use ``if key in request.args`` to check if a key is present. ``for key in request.args`` will iterate through the keys, or you can use ``request.args.keys()`` to get all of the keys.

Wyświetl plik

@ -452,8 +452,18 @@ def test_request_args():
request = Request.fake("/foo?multi=1&multi=2&single=3")
assert "1" == request.args.get("multi")
assert "3" == request.args.get("single")
assert "1" == request.args["multi"]
assert "3" == request.args["single"]
assert ["1", "2"] == request.args.getlist("multi")
assert [] == request.args.getlist("missing")
assert "multi" in request.args
assert "single" in request.args
assert "missing" not in request.args
expected = ["multi", "single"]
assert expected == list(request.args.keys())
for i, key in enumerate(request.args):
assert expected[i] == key
assert 2 == len(request.args)
with pytest.raises(KeyError):
request.args["missing"]