2


我試圖定義一個base request handling類,以便將Web應用程序的頁面可以繼承,否則將需要進行反覆的應用程序的每個頁面中定義的一些基本方法和變量。一種類似的功能,如django preprocessors。這是我的基類,其他頁面繼承:谷歌應用程序引擎,定義一個預處理類

class BasePage(webapp.RequestHandler): 
    def __init__(self):  
     self.user = users.get_current_user()  
     self.template_values = { 
       'user': self.user,  
       'environ': self, #I don't like the idea of passing the whole environ object to a template 

       ##The below three functions cannot be executed during _init_ because of absence of self.request 
       #'openid_providers': self.openid_providers(), 
       #'logout_url': self.get_logout_url(), 
       #'request': self.get_request(), 
      }   

    ##A sort of similar functionality like render_to_response in django 
    def render_template(self, template_name, values = None, *args, **kwargs): 
     #PATH is the directory containing the templates 
     if values: 
      for value in values: self.template_values[value] = values[value] 
     self.response.out.write(template.render(PATH+template_name, self.template_values, *args, **kwargs))     

    ##Returns request as the name suggests 
    def logout_url(self): 
     return users.create_logout_url(self.request.url) 

    ##Returns request as the name suggests 
    def request(self): 
     return request 

    ##Returns openid login urls   
    def openid_providers(self): 
     #OPENID_POVIDERS is a list of dictionary 
     for p in OPENID_PROVIDERS: 
      p['login_url'] = users.create_login_url(self.request.get('next', '/') , p['name'], p['url']) 
     return OPENID_PROVIDERS 

一切工作,除了爲self.request獲取不可用,我不能在初始化過程中通過一些變量的罰款。因此,對於解決方法,我所做的是將整個自變量作爲模板變量傳遞。

有一些其他的方式來提供模板變量(請求,logout_url等)的模板?

回答

2

我使用Template Method Pattern

基本上解決了這個問題,在我的AppEngine的代碼,基類的樣子:

class MyBasePage(webapp.RequestHandler): 
    def __init__(self): 
     # common setup/init stuff here, 
     # omitted for this discussion 

    def Setup(self): 
     # request handling setup code needed in both GET/POST methods, like 
     # checking for user login, getting session cookies, etc. 
     # omitted for this discussion 

    def get(self, *args): 
     self.Setup() 
     # call the derived class' 'DoGet' method that actually has 
     # the logic inside it 
     self.DoGet(*args) 

    def post(self, *args): 
     self.Setup() 
     # call the derived class' 'DoPost' method 
     self.DoPost(*args) 

    def DoGet(self, *args): 
     ''' derived classes override this method and 
      put all of their GET logic inside. Base class does nothing.''' 
     pass 

    def DoPost(self, *args): 
     ''' derived classes override this method and 
      put all of their POST logic inside. Base class does nothing.''' 
     pass 

...您的派生類則大多隻是需要擔心那些DoGet()DoPost()方法的膽量。

+0

的感謝!我正在考慮定義自定義get,基類中的帖子和使用super(),但是這個DoPost,DoGet似乎很棒!我認爲這對於我不需要很多django功能的小型項目來說非常有用。 – crodjer 2010-12-20 13:40:09

+0

@dcrodjer - 優秀! – bgporter 2010-12-20 13:58:41

5

比bgporter一個更簡單的解決方法是做普通設置在webapp.RequestHandlerinitialize方法。下面是來自工作,在這裏我們想一個Django樣is_ajax方法添加到請求對象的例子:

class BaseHandler(webapp.RequestHandler): 
    def initialize(self, request, response): 
     super(BaseHandler, self).initialize(request, response) 
     # Add a Django-like is_ajax() method to the request object 
     request.is_ajax = lambda: \ 
      request.environ.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest' 

這個方法被調用,嗯,初始化與當前的請求和響應對象的每個請求處理程序之前,調用適當的getpost(或其他)方法。

+0

+1 - 不錯;從來沒有考慮過。 – bgporter 2010-12-20 21:25:52

+0

是的,你可以做這樣的事情並不是很明顯。我不確定爲什麼處理程序不只是使用'__init__'來做同樣的事情。 – 2010-12-20 21:41:34

+0

不錯的解決方案@將! – crodjer 2011-01-01 06:29:24