Django HTTP 请求 get 与 getlist 的行为

6 投票
1 回答
9030 浏览
提问于 2025-04-17 12:20

我有一个Django表单,它会把一系列值提交到我的视图里。最开始我尝试用get方法来获取这个列表,但发现它只返回了最后一个值,后来才知道应该用getlist。经过一番摸索,我找到了一条已经关闭的Django bug,里面解释了这种行为的原因:

原因是,API方法应该始终返回字符串或列表,但不能同时返回两者。在网页应用中,表单的键通常只对应一个值,所以用[]这种语法来处理。而getlist()则是为了那些像你这种情况,想要用同一个键多次来获取多个值的场景。

我只是想知道这是否真的是一种最佳实践,因为它和其他数据结构,比如字典的get方法的工作方式是相矛盾的。

1 个回答

10

HTTP请求确实支持一个参数(键)可以有多个值。这就是为什么人们可以使用它们,并且有时候确实会使用它们。这也是Django引入了MultiValueDict结构的原因。

get()getlist()分开使用是有好处的,因为这样可以帮助你避免错误,并保持你的视图代码简单。想想其他的做法,它们都需要更多的代码来完成完全相同的事情:

  • get()总是返回一个列表。

    在大多数情况下,你只会给一个键传一个值,所以你需要加上[0]并提供一个默认值作为列表。

    param = request.GET.get('param', ['default value',])[0]

  • get()根据值的数量返回单个值或列表。

在HTML的选择框中,如果允许选择多个选项,这就成了一个问题。人们可以选择零个、一个或多个值。这意味着你需要自己把单个值转换成列表,或者反过来:

 params = request.GET.get('params', [])
 # Here you have absolutely no idea if this is a list or a single value
 # But you will need only one of that types

 # If you need list: ---------------------------------
 if not isinstance(params, list):
     params = [params,]

 objs = TestModel.objects.filter(id__in=params).all()

 # If you need single value: -------------------------
 if isinstance(params, list):
     params = params[0]   # Error if params is empty list...


obj = TestModel.objects.get(id=params)
  • get()总是返回单个值。那么在这种情况下,如果没有getlist,你该如何处理多个值呢?

所以,回答你的问题,get/getlist的行为是有额外价值的。

撰写回答