Google App Engine, дефинирайте клас за предварителна обработка


Опитвам се да дефинирам клас base request handling, така че страниците на webapp да могат да наследят някои основни методи и променлива, които иначе би трябвало да се дефинират многократно за всяка страница на приложението. Нещо като подобна функционалност като 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 и т.н.) към шаблоните?


person crodjer    schedule 20.12.2010    source източник


Отговори (2)


Реших този проблем в моя код на 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() методи.

person bgporter    schedule 20.12.2010
comment
Благодаря! Мислех за редове за дефиниране на персонализирано получаване, публикации в базовия клас и използване на super(), но този DoPost, DoGet изглежда страхотно!! Мисля, че това е добре за моя малък проект, който не се нуждае от много функции на django. - person crodjer; 20.12.2010

Много по-просто решение от това на bgporter е да направите общата настройка в initialize метода на webapp.RequestHandler. Ето пример от работа, където искахме да добавим подобен на 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'

Този метод се извиква, за да инициализира всеки манипулатор на заявка с текущите обекти на заявка и отговор, преди да бъдат извикани подходящите get или post (или каквито и да било) методи.

person Will McCutchen    schedule 20.12.2010
comment
Да, не е много очевидно как можете да правите такива неща. Не съм съвсем сигурен защо манипулаторите просто не използват __init__, за да направят същото. - person Will McCutchen; 21.12.2010