2011-10-01 139 views
3

在通用視圖Django的內部的基類在運行時創建的方法view,它重視的通用視圖類,然後調用這個類的調度方法爲什麼這個方法在這堂課中被採用?

我不明白這種做法的目的,爲什麼沒有調度方法是直接從as_view方法調用的?

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', '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 kwargs.iteritems(): 
      setattr(self, key, value) 

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

     def view(request, *args, **kwargs): 
      self = cls(**initkwargs) 
      return self.dispatch(request, *args, **kwargs) 

     # 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 
     self.request = request 
     self.args = args 
     self.kwargs = kwargs 
     return handler(request, *args, **kwargs) 

    def http_method_not_allowed(self, request, *args, **kwargs): 
     allowed_methods = [m for m in self.http_method_names if hasattr(self, m)] 
     logger.warning('Method Not Allowed (%s): %s' % (request.method, request.path), 
      extra={ 
       'status_code': 405, 
       'request': self.request 
      } 
     ) 
     return http.HttpResponseNotAllowed(allowed_methods) 

回答

4

在基於類的通用視圖,任何要求應該有它的MyView類的自己的實例。

這裏是我們的urls.py

from foo.views import AboutView 
.... 
(r'^about/', AboutView.as_view()), 

urls.py每線程的Django導入一次。這意味着調用as_view不會創建AboutView的實例。

當通過urlconf處理請求時,將調用view()方法,然後創建一個AboutView實例,並傳遞並填充此特定請求所需的所有相關數據。

使用:

(r'^about/', AboutView().dispatch), #WRONG!!!! 

將導致所有請求共享視圖的同一個實例,其中包括不應該再使用不同的請求可能屬性。

相關問題