日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

using werkzeug to build a shorly url app

發布時間:2023/12/8 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 using werkzeug to build a shorly url app 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • werkzeug構建'url shortly'應用
    • 0: basic wsgi
    • 1: creating the folders
    • 2: the base structure
    • 3: 環境
    • 4: routing
    • 5: first view
    • 6: redirect view
    • 7: detail view

werkzeug構建'url shortly'應用

參考教程: http://werkzeug.pocoo.org/docs/0.10/tutorial/

使用werkzeug構建一個快鍵url的應用, 有點類似于http://tinyurl.com/,在運行 服務器的時候,可以將自己指定的url存儲到redis 數據庫中,然后映射到一個數字上,然后通過服務器 地址加上我們的數字就可以很快鍵的訪問這個 url,并且可以對訪問的次數進行一個統計并 存到數據庫中。

在構建之前要在本地搭建好redis服務器,然后 還有pip安裝werkzeug, redis等自然不在話下。

0: basic wsgi

wsgi的hello world程序有點像這個樣子:

def application(environ, start_response):start_response('200 OK', [('Content-Type', 'text/plain')])return ['Hello World!']

因為wsgi程序都是接受一個參數environ和start_response, 然后開始這個響應并返回數據。

而使用werkzeug創建的wsgi程序如下:

from werkzeug.wrappers import Responsedef application(environ, start_response):response = Response('hello world',mimetype='text/plain'、)return response(environ, start_response)

這里同樣是在wsgi應用中創建一個響應對象并 返回調用這個函數的結果。

下面給wsgi應用一點小功能,就是能從請求中獲取 一個名字name并返回hello name.

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)

1: creating the folders

先創建好項目的文件夾目錄:

/shortly/static/templates

與其他慣例一樣,static放置一些靜態文件如css,js 還有圖片等,而templates文件夾放置html模板文件。

2: the base structure

整個項目需要用到的Import

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

下面就是我們的Shortly類,這個就是項目的主要 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 app
  • 初始化函數可以接受字典參數config,設置使用的

redis數據庫對象。

  • dispatch_request(request)函數顧名思義就是

分配請求,根據不同的請求返回不同的響應對象, 這里首先簡單的返回'hello world'的響應

wsgi_app(self, environ, start_response)函數 就是Shortly類中主要的wsgi應用,這里作為一個 函數成員存在,可以簡單理解這個函數就是一個 wsgi應用,而Shortly只是對其進行了一些包裝而已。

為了方便的調用Shortly對象,給其增加了__call__ 方法,其實就是返回self.wsgi_app(),這樣這個類 就可以方便的調用里面的wsgi方法了。

要運行這個應用,還需要有主函數

if __name__ == '__main__':from werkzeug.serving import run_simpleapp = create_app()run_simple('localhost',5000,app,# 訪問網頁出錯可以跟蹤錯誤信息use_debugger=True,# 修改服務器代碼的時候會自動重新加載use_reloader=True,)

現在直接運行我們的shortly.py就可以開啟服務器了。

$ python shortly.py* Running on http://127.0.0.1:5000/* Restarting with reloader: stat() polling

訪問這個地址就可以看到hello world

3: 環境

現在我們有了基本的wsgi應用,還需要處理 數據庫的創建還有模板渲染路徑等,可以在這個類 的初始化的時候實現

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)def render_template(self, template_name, **context):t = self.jinja_env.get_template(template_name)return Response(t.render(context), mimetype='text/plain',)

現在在初始化函數中加入模板的路徑,還有一個 jinja環境,類型是jinja2.Environment,這個 環境對象可以自己根據模板路徑來自動加載模板。

render_template函數可以返回一個經過模板渲染的 響應對象

4: routing

路由是非常重要的一部分,通過werkzeug.routing 模塊里面的Map對象建立路由規則,在里面定義 Rule對象。每個規則會嘗試匹配url并添加一個'endpoint',endpoint一般都是一個字符串,可以用來唯一 標識url,也可以用來翻轉url。

在__init__函數中添加:

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

這里的url處理其實和webpy也是類似的,第一個rule 說明'/'地址用new_url類來處理,即創建新url的界面 ,'/<short_id>'用'follow_short_link'來處理,意思 就是連接到這個id對應的url的網頁,如果后面加上'+' 就是第三個rule,用'short_link_details'來處理, 意思是顯示這個url的一些詳情,包括這個url的 訪問次數等。注意這里訪問的地址在第一個字符'/' 的前面其實都要加上服務器的地址。

有了這些url的映射關系,還要在dispatch的時候 根據這些url來返回不同的響應。假設我們對于每個 endpoint,采用'on_' + endpoint的函數來處理, 這樣我們只需要在dispatch的時候對不同的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, e:return e

前面我們已經在self.url_map這個Map類型的對象 中定義好url的映射規則,現在用bind_to_environ() 方法來獲取用戶訪問的地址等,綁定好之后就可以 調用match()方法來獲取用戶所訪問的url對應的 endpoint和values了。values是所捕獲的url中的一些參數,比如訪問http://localhost:5000/foo的時候 獲取到的數據如下:

endpoint = 'follow_short_link' values = {'short_id': u'foo'}

我們自己定義好'on_' _ endpoint函數之后將endpoint 和values參數傳入就可以自己來決定怎么處理

5: first view

現在先定義on_new_url函數怎么處理,首先這個 view有get和post兩種請求情況,如果是get情況則 返回一個創建新url的界面給用戶,如果是post請求 說明是用戶已經提交數據,則更新數據庫并且對 用戶做重定向。

class Shortly(...):...def on_new_url(self, request):error = Noneurl = ''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,)

這里需要輔助函數is_valid_url()來判斷一個用戶 輸入的url是否是合法的url。上面函數中,對于post請求,則在表單中提取用戶輸入的url,然后判斷,如果 合法,則調用輔助函數insert_url(url)將其存到 數據庫中,并且重定向到這個id下的detail界面。 如果是非法輸入或者get請求,則都用new_url.html 模板來渲染并返回。

一些輔助函數:

def is_valid_url(url):parts = urlparse.urlparse(url)return parts.scheme in ('http', 'https')def insert_url(self, url):short_id = self.redis.get('reverse-url:' + url)if shord_id is not None:return short_id # 這個url的id已經存在# 最后一個id+1之后作為新的url的idurl_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

insert函數中,每個url要添加兩項數據,一個是 url到id的映射,一個是id到url的映射即reverse. 在存儲id的時候,這里用了一個自定義的輔助函數 base36_encode()對id的數字進行了編碼。

def base36_encode(number):""">>> base36_encode(0)'0'>>> base36_encode(35)'z'"""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))

6: redirect view

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)

注意到這里如果數據庫沒有找到這個id則raise NotFound(),這樣在dispatch函數中就會返回一個404響應。

7: detail view

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)

處理方式和上一個類似,如果找不到該id就拋出錯誤。 找到的話則查詢它被訪問的次數并在最后返回。

到此為止整個應用就基本完成,最后就剩下一些 html模板文件和樣式表了。對于上面查詢數據庫沒有 找到id拋出的異常,可以在dispatch方法中對exception做一些處理,比如用404.html來進行渲染并返回。

轉載于:https://www.cnblogs.com/jolin123/p/4692439.html

總結

以上是生活随笔為你收集整理的using werkzeug to build a shorly url app的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。