在 google 应用引擎中创建受限页面

Creating restricted pages in google app engine

我在 Python Google App Engine 网站上创建管理页面时遇到问题。我认为答案应该很简单,但老实说,我一直在努力理解 类 如何从其他 类 继承,或者使用函数来包装其他函数,但我似乎无法理解很好地理解它。

基本上,我的网站有两种页面:主页,然后是一些允许用户执行管理操作的页面。任何人都可以在不登录的情况下看到主页。其他页面供管理员使用。唯一拥有帐户的用户是管理员,所以我设置了 webapp2 会话,只要

self.sessions.get('username')

returns 足以允许访问其他页面的内容。

这是我的处理程序:

class BaseHandler(webapp2.RequestHandler):
    def write(self, *a, **kw):
        self.response.out.write(*a, **kw)

    def render(self, template, **kw):
        self.response.out.write(render_str(template, **kw))

    def dispatch(self):
        # Get a session store for this request.
        self.session_store = sessions.get_store(request=self.request)

        try:
            # Dispatch the request.
            webapp2.RequestHandler.dispatch(self)
        finally:
            # Save all sessions.
            self.session_store.save_sessions(self.response)

    @webapp2.cached_property
    def session(self):
        # Returns a session using the default cookie key.
        return self.session_store.get_session()

class MainHandler(BaseHandler):
    def get(self):
        animals = Animal.query().fetch(100)
        self.render('index.html',animals=animals)

class AdminHandler(BaseHandler):
    def get(self):
        if self.session.get('username'):
            self.render('admin.html')
        else:
            self.render('signin.html')

class ReorderHandler(BaseHandler):
    def get(self):
        self.render('reorder.html')
    def post(self):
        #Change order of item display
        self.write('OK')

class DeleteHandler(BaseHandler):
    def get(self):
        self.render('delete.html')
    def post(self):
        #Delete entry from db
        self.write('OK')

class AddHandler(BaseHandler):
    def get(self):
        self.render('add.html')
    def post(self):
        #add entry to db
        self.write('OK')

class SigninHandler(BaseHandler):
    def post(self):
        #Check username and password
        if valid:
            self.session['username'] = username
            self.redirect('/admin')
        else:
            self.write('Not valid')

AdminHandler 列出了这些管理页面应该做什么的基本逻辑。 如果有人试图访问管理页面,处理程序应检查用户是否已登录,如果是,则允许访问该页面。如果没有,它会呈现登录页面。

重新排序、删除和添加都是我希望管理员能够执行的操作,但将来可能会有更多操作。我可以将 AdminHandler 逻辑添加到那些其他处理程序的所有 GET 和 POST,但这是非常重复的,因此我确信这是错误的做法。

正在寻找有关如何将 AdminHandler 的逻辑纳入涵盖 "administrative" 任务的所有其他处理程序的一些指导。

更新: Brent Washburne 为我指明了正确的方向,足以使它正常工作,尽管我仍然觉得我不了解装饰器函数的实际作用。无论如何,代码似乎可以正常工作,现在看起来像这样:

def require_user(old_func):
    def new_function(self):
        if not self.session.get('username'):
            self.redirect('/signin')
        old_func(self)
    return new_function

class AdminHandler(BaseHandler):
    @require_user
    def get(self):
        self.render('admin.html')

class AddHandler(BaseHandler):
    @require_user
    def get(self):
        self.render('add.html')
    @require_user
    def post(self):
        name = self.request.get('name')
        qry = Animal.query(Animal.name == name).get()
        if not qry:
            new_animal = Animal(name=name)
            new_animal.put()
        self.write('OK')

所有其他 "admin" 处理程序依此类推。

这是一种确保用户在每个页面(登录页面除外)都登录的蛮力方法,或者将用户重定向到登录页面:

def dispatch(self):
    # Get a session store for this request.
    self.session_store = sessions.get_store(request=self.request)

    if not self.session['username'] and self.request.get('path') != '/login':
        return redirect('/login')

更好的方法是将此代码添加到每个 get() 和 put() 例程的顶部:

def get(self):
    if not self.session['username']:
        return redirect('/login')

更好的方法是将该代码变成装饰器,这样您只需添加一行:

@require_login
def get(self):
    ....