Django 有函数视图和类视图,分别是这样用的:
# 函数视图
path(..., function_view, ...)
# 类视图
path(..., ClassView.as_view(), ...)
通过源码 as_view()
来看看它是如何把类转化成函数的。
class View:
...
@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.setup(request, *args, **kwargs)
if not hasattr(self, 'request'):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
)
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
- as_view() 是个类方法,它的第一个参数 cls 表示类本身,跟实例方法的 self 差不多,都是自动传入的。
- 进入 as_view() 后首先对传入的参数做简单的校验,避免传入的参数将类自己的关键函数名覆盖掉,或者传入类中没定义的属性。开头这个for 循环就是干这个用的。
- 接着 as_view() 内部又定义了一个 view() 函数,它接收的参数和普通的函数视图是相同的