慕工程0101907
我需要使用基于类的视图,但是我希望能够在URLconf中使用类的全名,而不必始终在使用它之前实例化视图类。帮助我的是一个非常简单的元类:class CallableViewClass(type):
def __call__(cls, *args, **kwargs):
if args and isinstance(args[0], HttpRequest):
instance = super(CallableViewClass, cls).__call__() return instance.__call__(*args, **kwargs) else:
instance = super(CallableViewClass, cls).__call__(*args, **kwargs) return instanceclass View(object):
__metaclass__ = CallableViewClass
def __call__(self, request, *args, **kwargs):
if hasattr(self, request.method):
handler = getattr(self, request.method) if hasattr(handler, '__call__'): return handler(request, *args, **kwargs) return HttpResponseBadRequest('Method Not Allowed', status=405)现在,我既可以实例化视图类,也可以将实例用作视图函数,或者我可以简单地将URLconf指向我的类,并让元类为我实例化(并调用)视图类。这是通过检查第一个参数__call__-如果它是a来实现的HttpRequest,它必须是一个实际的HTTP请求,因为试图用实例来实例化视图类是没有意义的HttpRequest。class MyView(View):
def __init__(self, arg=None):
self.arg = arg
def GET(request):
return HttpResponse(self.arg or 'no args provided')@login_requiredclass MyOtherView(View):
def POST(request):
pass# And all the following work as expected.urlpatterns = patterns(''
url(r'^myview1$', 'myapp.views.MyView', name='myview1'),
url(r'^myview2$', myapp.views.MyView, name='myview2'),
url(r'^myview3$', myapp.views.MyView('foobar'), name='myview3'),
url(r'^myotherview$', 'myapp.views.MyOtherView', name='otherview'),)