如何使用werkzeug建立WSGI APP

注意 :html

一、定義__call__的意義git

 

class App():
def __init__(self):
pass
def method(self):
pass

app=App()

app() #錯誤,由於app,即對象的實例,沒有括號運算符 github

 

 

class App2():
def __init__(self):
pass
def method(self):
pass
def __call__(self):
print 'call'

app2=App2()
app2() #print call     回去調用__call__裏面的內容redis

 

二、WSGI的Request和Response講解:app

 

 

三、自定義wsgi 程序框架

 

class Shortly(object):
def __init__(self, config):
self.redis = redis.Redis(config[‘redis_host’], config[‘redis_port’])

def dispatch_request(self, request):
return Response(‘Hello World!’)

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 appui

完成基本框架url

 

四、 繼續完善spa

在__init__ 裏面 渲染模板並鏈接到redis .net

 

def __init__(self, config):
self.redis = redis.Redis(config[‘redis_host’], config[‘redis_port’])
template_path = os.path.join(os.path.dirname(__file__), ‘templates’)
self.jinja_env = Environment(loader=FileSystemLoader(template_path),
autoescape=True)

## 建立一個Map實例,並增長一些Rule對象。每一個規則包含一個用來嘗試針對一個endpoint匹配URL的模式模板。endpoint一般是一個字符串,能夠用來惟一識別這個URL

## 另外一個帶有一樣的規則,只是在短連接以後增長了一個加號(+),將其鏈接到短連接的細節信息。

self.url_map = Map([
Rule(‘/’, endpoint=‘new_url’),
Rule(‘/<short_id>’, endpoint=‘follow_short_link’),
Rule(‘/<short_id>+’, endpoint=’short_link_details’)
])


def render_template(self, template_name, **context):
t = self.jinja_env.get_template(template_name)
return Response(t.render(context), mimetype=’text/html’)

 

## 添加視圖 view

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)

 

 

 

完整代碼下載:

# -*- coding: utf-8 -*-
"""
    shortly
    ~~~~~~~
    A simple URL shortener using Werkzeug and redis.
    :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details.
    :license: BSD, see LICENSE for more details.
"""
import os
import redis
import urlparse
from werkzeug.wrappers import Request, Response
from werkzeug.routing import Map, Rule
from werkzeug.exceptions import HTTPException, NotFound
from werkzeug.wsgi import SharedDataMiddleware
from werkzeug.utils import redirect

from jinja2 import Environment, FileSystemLoader


def base36_encode(number):
    assert number >= 0, 'positive integer required'
    if number == 0:
        return '0'
    base36 = []
    while number != 0:
        number, i = divmod(number, 36)
        base36.append('0123456789abcdefghijklmnopqrstuvwxyz'[i])
    return ''.join(reversed(base36))


def is_valid_url(url):
    parts = urlparse.urlparse(url)
    return parts.scheme in ('http', 'https')


def get_hostname(url):
    return urlparse.urlparse(url).netloc


class Shortly(object):

    def __init__(self, config):
        self.redis = redis.Redis(config['redis_host'], config['redis_port'])
        template_path = os.path.join(os.path.dirname(__file__), 'templates')
        self.jinja_env = Environment(loader=FileSystemLoader(template_path),
                                     autoescape=True)
        self.jinja_env.filters['hostname'] = get_hostname

        self.url_map = Map([
            Rule('/', endpoint='new_url'),
            Rule('/<short_id>', endpoint='follow_short_link'),
            Rule('/<short_id>+', endpoint='short_link_details')
        ])

    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 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
        )

    def error_404(self):
        response = self.render_template('404.html')
        response.status_code = 404
        return response

    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 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 NotFound, e:
            return self.error_404()
        except HTTPException, e:
            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 app


if __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)

 

 

https://github.com/pallets/werkzeug/tree/master/examples/shortly     含html頁面下載

相關文章
相關標籤/搜索