了解 python 中的请求参数

Understanding request parameters in python

我有下面的code。谁能帮我理解这段代码中到底发生了什么?

特别是self.request.GET.getpage < 1 and 1 or page部分。

def get(self, *v, **kv):
    page = int( self.request.GET.get('page', 1) )
    page = page < 1 and 1 or page
    items_per_page = int( self.request.GET.get('items_per_page', 500))
    items_per_page = items_per_page < 1 and 500 or items_per_page
    from_date = convert_to_utc(parse_datetime(self.request.GET.get('from')))[0] \
                or datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
    to_date = convert_to_utc(parse_datetime(self.request.GET.get('to')))[0]

self.request.GET 由 webapp2 框架通过 class 提供,其中实现了 get()。它为您的代码提供了对包含随 HTTP 请求发送的任何查询字符串参数的字典的访问权限,例如一个 URL 例如:

http://localhost/resource?page=1&items_per_page=20

在查询字符串中有两个参数:pageitems_per_page,分别具有值 1 和 20。 webapp2 处理 URL 并为您的应用程序提供包含这些参数的字典,例如self.request.GET 可能看起来像这样:

{'page': 1, 'items_per_page': 20, ...}

self.request.GET.get() 在字典中查找请求的键(例如 page),如果字典中存在该键,则 returns 它的值。如果键不在字典中,则返回默认值;对于 self.request.GET.get('page', 1),如果 URL 不包含 page 查询参数,则默认值为 1。有关详细信息,请参阅 dict.get()


如果查询字符串中提供的值小于 1,下一位是默认为第 1 页的讨厌方式:

page = page < 1 and 1 or page

可以这样写:

page = ((page < 1) and 1) or page

如果用户提供的页面值小于 1,则 page < 1 将为 True,然后 True and 1 将计算为 1 - 因此 1 用作值页。任何 >=1 的值都会导致 page < 1 成为 False,因此 or 子句将成为表达式的值。

这可以用更易读的方式重写,如下所示:

if page < 1:
    page = 1

或者像这样:

page = 1 if page < 1 else page

这更清楚地表明了代码的意图。

@mhawke 发布了一个很好的答案,但我仍然想扩展一下。

Here is the webapp2 documentation for the request object. I highly recommend taking a look at that, and also the Webob documentation 对于请求,因为 webapp2 请求和响应是从 Webob 框架中获取的(继续阅读响应文档)。

需要注意的一点是,GET数据是一个multi-dict,同样来自Webob框架。 multidict 基本上是一个字典,但一个键可以有多个值。这是来自 webapp2 文档的示例:

request = Request.blank('/test?check=a&check=b&name=Bob')

# The whole MultiDict:
# GET([('check', 'a'), ('check', 'b'), ('name', 'Bob')])
get_values = request.GET

# The last value for a key: 'b'
check_value = request.GET['check']

# All values for a key: ['a', 'b']
check_values = request.GET.getall('check')

# An iterable with all items in the MultiDict:
# [('check', 'a'), ('check', 'b'), ('name', 'Bob')]
request.GET.items()

如果您最终使用复选框为一个键提供值列表(表单上的 "check all that apply" 部分),该信息将派上用场。

因此在您的代码中,self.request.GET.get('page', 1) 正在从 multidict 中检索 page 的值,如果找不到该键,则 returning 1。同样的逻辑适用于键 items_per_pagefromto:检索该键的值,如果找不到该键,则 return 提供默认值.

然后你有这两行:

page = page < 1 and 1 or page

items_per_page = items_per_page < 1 and 500 or items_per_page

正如@mhawke 所说,这是一种令人讨厌的说法:

if page < 1:
    page = 1
if items_per_page < 1:
    items_per_page = 500

事实上,如果有机会,您应该更改该代码以使其更具可读性。