在 index.py 和 single_post.py 中, 请求处理器
Index
跟 SinglePost
的代码重复的部分还是挺多的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,
}))
从上面的对比看来, 很明显, 对于日常情况中的请求, 服务器端重要的的响应参数包括
- 模板文件的相对路径
- 交给模板的参数
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'),
})
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 %}
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)