基于类的视图:为什么 Django/DRF 中的 URL 参数进入 `self.kwargs` 而不是另一个属性(例如,`self.url_params`)?

问题描述 投票:0回答:1

在使用 Django/Django Rest Framework 时,我注意到基于类的视图中访问 URL 参数的方式不一致。


问题描述

在基于通用类的视图中,我可以通过两种不同的方式访问 URL 参数 - 取决于方法:

  1. 通过位置参数: 例如,在
    get
    方法中,我可以访问 URL 参数作为直接传递给方法的位置参数:
#urls.py
path('test/<str:param1>/<int:param2>/', MyView.as_view())
#views.py
class MyView(View):
    def get(self, request, param1, param2):
        return JsonResponse({'param1': param1, 'param2': param2})
  1. self.kwargs
    属性 例如,当我想在
    get_queryset
    方法中访问相同的参数时,我必须使用
    self.kwargs
#views.py
class MyView(ListView):
    model = MyModel

    def get_queryset(self):
        param1 = self.kwargs.get('param1')
        param2 = self.kwargs.get('param2')
        return MyModel.objects.filter(field1=param1, field2=param2)

我知道我可以从
kwargs
任何地方访问 url 参数,但这让我产生了一些问题

我的问题:

  • 为什么 Django/DRF 没有引入 URL 参数的专用属性?将这些参数存储在专用属性(例如
    self.url_params
    )中不是更直观吗 - 是否有任何具体原因为什么
    self.kwargs
    命名是首选 - 我得到了约定,但对我来说有点困惑,我们有很多其他属性,例如 idk
    self.data
    self.method
    ,但我们没有 url 属性。
  • 为什么 Django 的文档中没有明确解释
    self.kwargs
    机制。当我试图找出原因时,我有点头疼。该机制对于使用基于类的视图似乎至关重要,但我找不到明确的解释。相反,文档仅提供示例,似乎希望开发人员“推断”URL 参数存储在 self.kwargs 中。

任何人都可以解释为什么会出现这种情况吗?我很感激有关此设计决策的任何见解或解释。

python django django-rest-framework django-views
1个回答
0
投票

通过位置参数

参数不是按位置传递,而是作为命名参数传递。事实上,如果你改变你的观点:

class MyView(View):
    def get(self, request, param2, param1):  # 🖘 different order
        return JsonResponse({'param1': param1, 'param2': param2})

它仍然会以完全相同的方式工作。

为什么 Django/DRF 没有引入 URL 参数的专用属性?

我的猜测是你本身并不想要这样。您可以传递任意额外的 kwargs,常见的模式是:

urlpatterns = [
    path('test/<str:param1>/<int:param2>/', MyView.as_view()),
    path('test/<str:param1>/', MyView.as_view(), kwargs={'param2': 0}),
]

因此部分

kwargs
源自 URL 路径模式,其他部分是硬编码的,例如使路径片段可选

本质上,

.kwargs
是视图“触发”的一组参数,这些参数本身并非来自 URL。

如果您只想要 URL 中的内容,您可以使用:

self.request.resolver_match.captured_kwargs  # the ones explicitly mentioned in URL

为什么 Django 的文档中没有明确解释 self.kwargs 机制。

内置基于类的通用视图部分中隐约提到了[Django-doc]

实现这项工作的关键部分是,当调用基于类的视图时,各种有用的东西都存储在 self 上;以及请求 (

self.request
),这包括根据 URLconf 捕获的位置 (
self.args
) 和基于名称 (
self.kwargs
) 参数

但我同意这可能还不够。主要问题是设置

self.args
self.kwargs
self.request
不是一成不变的:它发生在 .setup(…)
 方法
[Django-doc] 中,尽管重写它是
非常不明智,你可以改变这种行为。我已经打开了ticket[Django-ticket]来重写文档,并使其更清楚发生了什么。

© www.soinside.com 2019 - 2024. All rights reserved.