2

Ich versuche, eine base request handling Klasse zu definieren, so dass die Webapp-Seiten einige grundlegende Methoden und Variablen erben, die sonst für jede Seite der Anwendung wiederholt definiert werden müssten. Eine Art ähnlicher Funktionalität wie django preprocessors. Das ist meine Basisklasse, von der anderen Seiten erben:Google App Engine, definieren Sie eine Vorlaufklasse

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 

Alles funktioniert, außer in Ordnung, dass ich nicht einige Variablen während der Initialisierung passieren kann als self.request nicht verfügbar ist. Für eine Problemumgehung habe ich also eine ganze Eigenvariable als Template-Variable übergeben.

Gibt es eine andere Möglichkeit, die Template-Variablen (request, logout_url usw.) den Templates zur Verfügung zu stellen?

Antwort

2

ich dieses Problem in meinem App Engine-Code gelöst haben, indem die Template Method Pattern

mit Grundsätzlich sieht die Basisklasse wie:

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 

... Ihre abgeleiteten Klassen dann meist nur darum kümmern müssen die Eingeweide dieser DoGet() und DoPost() Methoden.

+0

danke! Ich dachte in Zeilen der Definition benutzerdefinierte get, Beiträge in der Basisklasse und mit super(), aber diese DoPost, DoGet scheint toll !! Ich denke, das ist gut für mein kleines Projekt, das nicht viele Django-Features benötigt. – crodjer

+0

@dcrodjer - ausgezeichnet! – bgporter

5

Eine viel einfachere Lösung als bgporter ist die gemeinsame Einrichtung in der initialize Methode von webapp.RequestHandler. Hier ist ein Beispiel von der Arbeit, wo wir eine Django-like is_ajax Methode zum Request-Objekt hinzufügen wollte:

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' 

Diese Methode wird aufgerufen, äh, initialisieren jeden Request-Handler mit den aktuellen Anfrage und Antwort Objekte, vor die entsprechenden get oder post (oder was auch immer) Methoden werden aufgerufen.

+0

+1 - nett; hat das nie bedacht. – bgporter

+0

Ja, es ist nicht sehr offensichtlich, wie man solche Dinge tun kann. Ich bin mir nicht ganz sicher, warum die Handler nicht einfach "__init__" benutzen, um dasselbe zu tun. –

+0

nette Lösung @will! – crodjer