本文共 4739 字,大约阅读时间需要 15 分钟。
Werkzeug 不是框架,而是一个库,用于开发应用程序和框架。它提供了一套工具,帮助开发者构建高效的 Web 应用程序。
WSGI 应用程序的基本结构如下:
def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return ['Hello World!'] WSGI 应用程序是一个可调用的函数,接受 environ(包含请求信息的字典)和 start_response(开始响应的可调用对象)。environ 包含了所有请求的信息,而 start_response 表示开始处理响应。
使用 Werkzeug,可以将请求和响应进一步封装。例如:
from werkzeug.wrappers import Request, Responsedef application(environ, start_response): request = Request(environ) text = 'Hello %s!' % request.args.get('name', 'World') response = Response(text, mimetype='text/plain') return response(environ, start_response) 创建项目时,首先需要创建文件夹结构:
/shortly /static /templates
在 /shortly 文件夹下创建 shortly.py 文件:
import osimport redisfrom werkzeug.wrappers import Request, Responsefrom werkzeug.routing import Map, Rulefrom werkzeug.exceptions import HTTPException, NotFoundfrom werkzeug.middleware.shared_data import SharedDataMiddlewarefrom werkzeug.utils import redirectfrom jinja2 import Environment, FileSystemLoaderclass Shortly: def __init__(self, config): self.redis = redis.Redis(config['redis_host'], config['redis_port']) self.template_path = os.path.join(os.path.dirname(__file__), 'templates') self.jinja_env = Environment(loader=FileSystemLoader(self.template_path), autoescape=True) def render_template(self, template_name, **context): t = self.jinja_env.get_template(template_name) return Response(t.render(context), mimetype='text/html') def dispatch_request(self, request): adapter = self.url_map.bind_to_environ(request.environ) try: endpoint, values = adapter.match() return getattr(self, 'on_' + endpoint)(request, **values) except HTTPException: return e def wsgi_app(self, environ, start_response): request = Request(environ) response = self.dispatch_request(request) return response(environ, start_response) def __call__(self, environ, start_response): return self.wsgi_app(environ, start_response)def create_app(redis_host='localhost', redis_port=6379, with_static=True): app = Shortly({ 'redis_host': redis_host, 'redis_port': redis_port }) if with_static: app.wsgi_app = SharedDataMiddleware(app.wsgi_app, { '/static': os.path.join(os.path.dirname(__file__), 'static') }) return appif __name__ == '__main__': from werkzeug.serving import run_simple app = create_app() run_simple('127.0.0.1', 5000, app, use_debugger=True, use_reloader=True) 运行项目:
python shortly.py
项目结构可以扩展,例如添加模板渲染和 Redis 连接:
def __init__(self, config): self.redis = redis.Redis(config['redis_host'], config['redis_port']) self.template_path = os.path.join(os.path.dirname(__file__), 'templates') self.jinja_env = Environment(loader=FileSystemLoader(self.template_path), autoescape=True)
路由可以通过 Werkzeug 的 Map 和 Rule 类实现:
self.url_map = Map([ Rule('/', endpoint='new_url'), Rule('/ ', endpoint='follow_short_link'), Rule('/ +', endpoint='short_link_details')]) URL 路由的匹配和处理:
def dispatch_request(self, request): adapter = self.url_map.bind_to_environ(request.environ) try: endpoint, values = adapter.match() return getattr(self, 'on_' + endpoint)(request, **values) except HTTPException: return e
视图函数的实现:
def on_new_url(self, request): error = None url = '' if request.method == 'POST': url = request.form['url'] if not is_valid_url(url): error = 'Please enter a valid URL' else: short_id = self.insert_url(url) return redirect('/%s+' % short_id) return self.render_template('new_url.html', error=error, url=url) 数据库处理:
def insert_url(self, url): short_id = self.redis.get('reverse-url:' + url) if short_id is not None: return short_id url_num = self.redis.incr('last-url-id') short_id = base36_encode(url_num) self.redis.set('url-target:' + short_id, url) self.redis.set('reverse-url:' + url, short_id) return short_id 查看链接点击次数:
def on_follow_short_link(self, request, short_id): link_target = self.redis.get('url-target:' + short_id) if link_target is None: raise NotFound() self.redis.incr('click-count:' + short_id) return redirect(link_target) 查看链接详情:
def on_short_link_details(self, request, short_id): link_target = self.redis.get('url-target:' + short_id) if link_target is None: raise NotFound() click_count = int(self.redis.get('click-count:' + short_id) or 0) return self.render_template('short_link_details.html', link_target=link_target, short_id=short_id, click_count=click_count) 该项目结合了 Werkzeug 的强大功能和 Redis 的高效存储,能够创建一个灵活的 URL 短链接服务。
转载地址:http://hgefk.baihongyu.com/