基于 Django 类的视图:了解视图类中的参数

Posted

技术标签:

【中文标题】基于 Django 类的视图:了解视图类中的参数【英文标题】:Django Class Based Views: Understanding the arguments in the view class 【发布时间】:2015-04-30 11:56:23 【问题描述】:

通读View Class的源代码

源代码:

class View(object):
"""
Intentionally simple parent class for all views. Only implements
dispatch-by-method and simple sanity checking.
"""

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

def __init__(self, **kwargs):
    """
    Constructor. Called in the URLconf; can contain helpful extra
    keyword arguments, and other things.
    """
    # Go through keyword arguments, and either save their values to our
    # instance, or raise an error.
    for key, value in six.iteritems(kwargs):
        setattr(self, key, value)

@classonlymethod
def as_view(cls, **initkwargs):
    """
    Main entry point for a request-response process.
    """
    for key in initkwargs:
        if key in cls.http_method_names:
            raise TypeError("You tried to pass in the %s method name as a "
                            "keyword argument to %s(). Don't do that."
                            % (key, cls.__name__))
        if not hasattr(cls, key):
            raise TypeError("%s() received an invalid keyword %r. as_view "
                            "only accepts arguments that are already "
                            "attributes of the class." % (cls.__name__, key))

    def view(request, *args, **kwargs):
        self = cls(**initkwargs)
        if hasattr(self, 'get') and not hasattr(self, 'head'):
            self.head = self.get
        self.request = request
        self.args = args
        self.kwargs = kwargs
        return self.dispatch(request, *args, **kwargs)
    view.view_class = cls
    view.view_initkwargs = initkwargs

    # take name and docstring from class
    update_wrapper(view, cls, updated=())

    # and possible attributes set by decorators
    # like csrf_exempt from dispatch
    update_wrapper(view, cls.dispatch, assigned=())
    return view

def dispatch(self, request, *args, **kwargs):
    # Try to dispatch to the right method; if a method doesn't exist,
    # defer to the error handler. Also defer to the error handler if the
    # request method isn't on the approved list.
    if request.method.lower() in self.http_method_names:
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
        handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)

def http_method_not_allowed(self, request, *args, **kwargs):
    logger.warning('Method Not Allowed (%s): %s', request.method, request.path,
        extra=
            'status_code': 405,
            'request': request
        
    )
    return http.HttpResponseNotAllowed(self._allowed_methods())

我的理解是,加载urlconf时,会调用as_view class only方法。 as_view 调用 view 方法,该方法用 self= cls(**initkwargs) 实例化一个 View 对象,然后 __init__ 运行。

我对弄清楚view 方法所采用的**kwargs 与实例化类时使用的**initkwargs 之间的区别感到困惑。我假设view 方法通过**kwargs 传递所有参数...那么为什么self= cls(**initkwargs) 行不写为self = cls(**kwargs)

**initkwargs**kwargs 有什么区别?

【问题讨论】:

【参考方案1】:

as_view 调用view 方法,该方法用self= cls(**initkwargs) 实例化View 对象,然后__init__ 运行。

实际上不,这没有发生。 as_view 没有调用view 函数(view 不是方法),as_view 创建view 函数并返回它,因此可以稍后调用。 initkwargs 在处理 urlpatterns 时被传递给 as_viewkwargs 在 URL 调度程序在检索特定 url 时调用它时被传递到视图中。这就是为什么kwargsinitkwargs 不是一回事。

【讨论】:

**initkwargs**kwargs 的值是否不同? URL 调度程序将 view(request, **args, **kwargs) 包含在 URL 中的参数作为 **kwargs 传递,对吗?那么**initkwarg 的值是什么?它们是否也在 URL 中找到?还是它们来自其他地方? 没关系,我明白。例如,可以使用 TemplateView 子类化基本视图类。如果这样做,您可以通过将默认模板名称传递给 as_view 来覆盖它。然后,来自 URL 的参数被进一步添加到视图函数中【参考方案2】:

代码只是明确区分了您从 urlconf 传递到视图类本身的实例化的硬编码 kwargs,以及您在实际调用视图时从 URL 传递的动态 kwargs .

【讨论】:

以上是关于基于 Django 类的视图:了解视图类中的参数的主要内容,如果未能解决你的问题,请参考以下文章

Django后端开发学习笔记Django REST Framework基于类的视图

如何正确地将参数传递给 Django 中的基于类的视图实例?

将基于缓存 Django 类的视图响应与请求中的参数绑定

如何正确地将参数传递给基于类的视图测试 Django Rest Framework?

Django编写RESTful API:基于类的视图

带有参数的 Django 反向 url 到基于类的视图