About
RSS

Bit Focus


GAE 速成简易博客 - 简化 RequestHandler

Posted at 2012-01-23 07:17:09 | Updated at 2024-12-24 03:48:28

上节回顾 - 进阶数据库操作

在 index.py 和 single_post.py 中, 请求处理器 IndexSinglePost 的代码重复的部分还是挺多的
class SinglePost(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__),
                            'templates/single_post.html')
        posts = db.GqlQuery('SELECT * FROM Post WHERE pid = :1',
                            int(self.request.get('id')))
        self.response.out.write(template.render(path, {
                'post': posts[0],
            }))

class Index(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'templates/index.html')
        posts = db.GqlQuery('SELECT * FROM Post ORDER BY date DESC')
        self.response.out.write(template.render(path, {
                'posts': posts,
            }))
作为程序员, 应该对这样的重复代码零容忍, 当机立断, 大刀阔斧来改起!

    从上面的对比看来, 很明显, 对于日常情况中的请求, 服务器端重要的的响应参数包括
    那么很好, 来弄个基类, 新建个 base.py 放进去
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
import os

class BaseHandler(webapp.RequestHandler):
    def put_page(self, templ_file, templ_args):
        path = os.path.join(os.path.dirname(__file__), templ_file)
        self.response.out.write(template.render(path, templ_args))
    开始用新的 BaseHandler 搞起吧.
    先来搞 index.py
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext import db
import os

import base

class Index(
            # webapp.RequestHandler
            base.BaseHandler):
    def get(self):
        # path = os.path.join(os.path.dirname(__file__), 'templates/index.html')
        # posts = db.GqlQuery('SELECT * FROM Post ORDER BY date DESC')
        # self.response.out.write(template.render(path, {
        #         'posts': posts,
        #     }))
        self.put_page('templates/index.html', {
                'posts': db.GqlQuery('SELECT * FROM Post ORDER BY date DESC'),
            })
    而 single_post.py 也可以修改得一样简洁
from google.appengine.ext import db

import base

class SinglePost(base.BaseHandler):
    def get(self):
        self.put_page('templates/single_post.html', {
                'post': db.GqlQuery('SELECT * FROM Post WHERE pid = :1',
                                    int(self.request.get('id')))[0],
            })
    对于像 AddPostEntry 这样不需要传给模板参数的, 则可以通过给 put_page 参数加上默认值来简化
class BaseHandler(webapp.RequestHandler):
    def put_page(self, templ_file, templ_args=dict()):
        path = os.path.join(os.path.dirname(__file__), templ_file)
        self.response.out.write(template.render(path, templ_args))
    那么 AddPostEntry 可以改成
import base

class AddPostEntry(base.BaseHandler):
    def get(self):
        self.put_page('templates/add_post.html')
    重构之后再写新的 RequestHandler 就容易许多了.

    那趁热打铁, 先来弄个 404 页面. 当用户访问了不正确的 URL 时, 塞给用户一些最近发布的文章. 如下, 在新文件 templates/notfound.html 中
<html>
<head><title>Not Found - My Blog</title></head>
<body>
<h1>Oops..</h1>
Content not found. Would you like to read recent posts?
{% for post in posts %}
<p><a href='/p?id={{ post.pid }}'>{{ post.title }}</a></p>
{% endfor %}
    接着新建文件 notfound.py
from google.appengine.ext import db

import base

class NotFound(base.BaseHandler):
    def get(self):
        self.error(404)
        self.put_page('templates/notfound.html', {
                'posts': db.GqlQuery('SELECT * FROM Post ORDER BY date DESC')
                            .fetch(4),
            })
    与一般 RequestHandler 不同的是, NotFound 需要设置 HTTP 错误码为 404, 否则, 浏览器会认为一切正常, 并在浏览记录中保留用户访问的错误 URL.
    另外, 这次 GqlQuery 带了一个小尾巴, fetch(4) 表示只取出 4 条数据.

    最后, 在 main.py 的 URL 映射列表中, 在列表末尾增加一项
application = webapp.WSGIApplication([
    ('/', index.Index),
    ('/p', single_post.SinglePost),
    ('/add_post', add_post.AddPostEntry),
    ('/add_post_do', add_post.AddPostHandler),
    ('/.*', notfound.NotFound),
], debug=True)
    大功告成.

Post tags:   Web Server  Google AppEngine  Tutorial  Python

Leave a comment:




Creative Commons License Your comment will be licensed under
CC-NC-ND 3.0


. Back to Bit Focus
NijiPress - Copyright (C) Neuron Teckid @ Bit Focus
About this site