我在这里看到两个问题:
- 关于的误解
class-based views
in django
- 关于的误解
object-
and class-
中的方法python
让我们更详细地看看。
1. Django 基于类的视图
听起来一定很奇怪(尤其是对于新人)但是class-based view
在 django 中并不意味着你绑定的方法objects
/classes
to url
-路线。
更是如此:
django.urls.path
只能使用以下函数fn(request, *args, **kwargs)
Pythonicit's better explicite
for self
-param 使object-methods
无法用于views
(至少没有“特殊魔法”)。
那么什么意思class-based views
?
https://github.com/django/django/blob/2bc014750adb093131f77e4c20bc17ba64b75cac/django/views/generic/base.py#L48 https://github.com/django/django/blob/2bc014750adb093131f77e4c20bc17ba64b75cac/django/views/generic/base.py#L48
其实很简单:
-
class-based view
暴露类方法as_view
-
as_view
是一个高阶函数,不直接使用path
/url
calls.
-
as_view
在运行时构造实际的视图函数
- 生成的函数也不是很复杂。粗略地说,它寻找定义的存在
get
/post
/put
/head
-方法,当它们存在时调用它们,当它们不存在时引发异常。
所以你可以看到“在 django 中,并不是简单地将 class-view 的方法绑定到 url-routes”。
对于一般情况来说,很难推荐使用这种工具,但在需要这种不灵活性的情况下,它效果很好。
2. object-
,class-
, static-
methods
好的。现在第二个问题。
我们可以从以下方法调用class-based view
其他方法?
是的,我们可以,但有一些限制。
让我们看看one-file
django 2.0 中的演示。 (对于 1.11 -%s/path/url/g
)
from django.urls import path
from django.http import HttpResponse
from django.utils.decorators import classonlymethod
# CASE 1: normal function - OK
def just_a_fun(request, **kwargs):
context = kwargs if kwargs else {"method": "just a function"}
return HttpResponse('method = %(method)s' % context)
class ViewClass(object):
def get(self, request, **kwargs):
return just_a_fun(request, **kwargs)
# CASE 2: Object method - FAIL, not possible to use in `django.url.path`-calls
def om_view(self, request):
return self.get(request, **{"method": "object method"})
# CASE 3: class method - OK
@classmethod
def cm_view(cls, request):
return cls.get(cls, request, **{"method": "class method"})
# CASE 4: static method - FAIL, not possible to call `cls.get` or `self.get`
@staticmethod
def sm_view(request):
self = None # This is a problem with static methods
return self.get(self, request, **{"method": "static method"})
# CASE 5: HOF-view, similar to django.views.generic.View.as_view - OK
@classonlymethod
def as_view(cls, **initkwargs):
def view(request, **kwargs):
self = cls(**initkwargs) # Object construction
self.request = request
self.kwargs = kwargs
return self.get(request, **{"method": "HOF as_view"})
return view
urlpatterns = [
path("just-a-fun", just_a_fun), # OK
path("object-method",
ViewClass.om_view), # Problem: redundant `self` for `path`
path("class-method", ViewClass.cm_view), # OK
path('static-method',
ViewClass.sm_view), # Problem: not possible to call `get`
path('hof-view', ViewClass.as_view()), # OK.
]
Summary:
- 一般来说,普通函数是最好的
- 对象方法不可用(至少没有一些“特殊魔法”)
- 类方法:没有问题。但请记住,类方法只能使用其他类方法
- 静态方法:可以用于
path
/url
调用但不能使用类的其他方法
- 如果你真的想使用 OOP:你可以用“django 方式”来实现 - 创建 HOF,它将在运行时生成实际的视图函数。看着
django.views.generic
灵感源代码
...
我希望这必须澄清问题,但欢迎提出问题、批评、指正!