成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Flask Web Development —— 大型應(yīng)用程序結(jié)構(gòu)(上)

chemzqm / 1784人閱讀

摘要:被定義在包的構(gòu)造函數(shù)中的應(yīng)用程序工廠函數(shù)會(huì)在示例中展示。這個(gè)構(gòu)造函數(shù)導(dǎo)入大部分當(dāng)前需要使用的擴(kuò)展,但因?yàn)闆]有應(yīng)用程序?qū)嵗跏蓟鼈?,它可以被?chuàng)建但不初始化通過不傳遞參數(shù)給它們的構(gòu)造函數(shù)。而應(yīng)用程序范圍內(nèi)的錯(cuò)誤處理則必須使用。

雖然小型web應(yīng)用程序用單個(gè)腳本可以很方便,但這種方法卻不能很好地?cái)U(kuò)展。隨著應(yīng)用變得復(fù)雜,在單個(gè)大的源文件中處理會(huì)變得問題重重。

與大多數(shù)其他web框架不同,F(xiàn)lask對(duì)大型項(xiàng)目沒有特定的組織方式;應(yīng)用程序的結(jié)構(gòu)完全交給開發(fā)人員自己決定。在這一章,提出一個(gè)可能的方式來組織管理一個(gè)大型應(yīng)用程序的包和模塊。這種結(jié)構(gòu)將用于書中其余的示例中。

1、項(xiàng)目結(jié)構(gòu)

示例7-1展示基本Flask應(yīng)用程序結(jié)構(gòu)

示例7-1:基本多文件Flask應(yīng)用結(jié)構(gòu)

|-flasky
  |-app/
    |-templates/
    |-static/
    |-main/
      |-__init__.py
      |-errors.py
      |-forms.py
      |-views.py
    |-__init__.py
    |-email.py
    |-models.py
  |-migrations/
  |-tests/
    |-__init__.py
    |-test*.py
  |-venv/
  |-requirements.txt
  |-config.py
  |-manage.py

這個(gè)結(jié)構(gòu)有四個(gè)頂層目錄:

Flask應(yīng)用一般放置在名為app的目錄下。

migrations目錄包含數(shù)據(jù)庫遷移腳本,這和之前說的一樣。

單元測試放置在test目錄下

venv目錄包含Python虛擬環(huán)境,這和之前說的也是一樣的。

還有一些新的文件:

requirements.txt列出一些依賴包,這樣就可以很容易的在不同的計(jì)算機(jī)上部署一個(gè)相同的虛擬環(huán)境。

config.py存儲(chǔ)了一些配置設(shè)置。

manage.py用于啟動(dòng)應(yīng)用程序和其他應(yīng)用程序任務(wù)。

為了幫助你完全理解這個(gè)結(jié)構(gòu),下面會(huì)描述將hello.py應(yīng)用改為符合這一結(jié)構(gòu)的整個(gè)流程。

2、配置選項(xiàng)

應(yīng)用程序通常需要幾個(gè)配置設(shè)置。最好的例子就是在開發(fā)過程中需要使用不同的數(shù)據(jù)庫,測試,生產(chǎn)環(huán)境,這樣他們可以做到互不干擾。

我們可以使用配置類的層次結(jié)構(gòu)來代替hello.py中的簡單類字典結(jié)構(gòu)配置。示例7-2展示了config.py文件。

示例7-2. config.py:應(yīng)用程序配置

import os
basedir = os.path.abspath(os.path.dirname(__file__))

class Config:
    SECRET_KEY = os.environ.get("SECRET_KEY") or "hard to guess string" 
    SQLALCHEMY_COMMIT_ON_TEARDOWN = True
    FLASKY_MAIL_SUBJECT_PREFIX = "[Flasky]"
    FLASKY_MAIL_SENDER = "Flasky Admin " 
    FLASKY_ADMIN = os.environ.get("FLASKY_ADMIN")
    
    @staticmethod
    def init_app(app): 
        pass

class DevelopmentConfig(Config): 
    DEBUG = True

    MAIL_SERVER = "smtp.googlemail.com"
    MAIL_PORT = 587
    MAIL_USE_TLS = True
    MAIL_USERNAME = os.environ.get("MAIL_USERNAME")
    MAIL_PASSWORD = os.environ.get("MAIL_PASSWORD") 
    SQLALCHEMY_DATABASE_URI = os.environ.get("DEV_DATABASE_URL") or 
        "sqlite:///" + os.path.join(basedir, "data-dev.sqlite")

class TestingConfig(Config): 
    TESTING = True
    SQLALCHEMY_DATABASE_URI = os.environ.get("TEST_DATABASE_URL") or 
        "sqlite:///" + os.path.join(basedir, "data-test.sqlite")

class ProductionConfig(Config):
    SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL") or 
        "sqlite:///" + os.path.join(basedir, "data.sqlite")

config = {
    "development": DevelopmentConfig,
    "testing": TestingConfig,
    "production": ProductionConfig,
    "default": DevelopmentConfig
}

Config基類包含一些相同配置;不同的子類定義不同的配置。額外配置可以在需要的時(shí)候在加入。

為了讓配置更靈活更安全,一些設(shè)置可以從環(huán)境變量中導(dǎo)入。例如,SECRET_KEY,由于它的敏感性,可以在環(huán)境中設(shè)置,但如果環(huán)境中沒有定義就必須提供一個(gè)默認(rèn)值。

在三個(gè)配置中SQLALCHEMY_DATABASE_URI變量可以分配不同的值。這樣應(yīng)用程序可以在不同的配置下運(yùn)行,每個(gè)可以使用不同的數(shù)據(jù)庫。

配置類可以定義一個(gè)將應(yīng)用程序?qū)嵗鳛閰?shù)的init_app()靜態(tài)方法。這里特定于配置的初始化是可以執(zhí)行的。這里Config基類實(shí)現(xiàn)一個(gè)空init_app()方法。

在配置腳本的底部,這些不同的配置是注冊(cè)在配置字典中。將其中一個(gè)配置(開發(fā)配置)注冊(cè)為默認(rèn)配置。

3、應(yīng)用程序包

應(yīng)用程序包放置了所有應(yīng)用程序代碼、模板和靜態(tài)文件。它被簡單的稱為app,也可以給定一個(gè)特定于應(yīng)用的名稱(如果需要的話)。templatesstatic目錄是應(yīng)用的一部分,因此這兩個(gè)目錄應(yīng)該放置在app中。數(shù)據(jù)庫模型和電子郵件支持功能也要置入到這個(gè)包中,每個(gè)都以app/models.pyapp/email.py形式存入自己的模塊當(dāng)中。

3.1、使用一個(gè)應(yīng)用程序工廠

在單個(gè)文件中創(chuàng)建應(yīng)用程序的方式非常方便,但是它有一個(gè)大缺點(diǎn)。因?yàn)閼?yīng)用程序創(chuàng)建在全局范圍,沒有辦法動(dòng)態(tài)的適應(yīng)應(yīng)用配置的更改:腳本運(yùn)行時(shí),應(yīng)用程序?qū)嵗呀?jīng)創(chuàng)建,所以它已經(jīng)來不及更改配置。對(duì)于單元測試這是特別重要的,因?yàn)橛袝r(shí)需要在不同的配置下運(yùn)行應(yīng)用程序來獲得更好的測試覆蓋率。

解決這一問題的方法就是將應(yīng)用程序放入一個(gè)工廠函數(shù)中來延遲創(chuàng)建,這樣就可以從腳本中顯式的調(diào)用。

這不僅給腳本充足的時(shí)間來設(shè)置配置,也能用于創(chuàng)建多個(gè)應(yīng)用程序?qū)嵗恍┰跍y試過程中非常有用的東西。被定義在app包的構(gòu)造函數(shù)中的應(yīng)用程序工廠函數(shù)會(huì)在示例7-3中展示。

這個(gè)構(gòu)造函數(shù)導(dǎo)入大部分當(dāng)前需要使用的擴(kuò)展,但因?yàn)闆]有應(yīng)用程序?qū)嵗跏蓟鼈?,它可以被?chuàng)建但不初始化通過不傳遞參數(shù)給它們的構(gòu)造函數(shù)。create_app()即應(yīng)用程序工廠函數(shù),需要傳入用于應(yīng)用程序的配置名。配置中的設(shè)置被保存在config.py中的一個(gè)類中,可以使用Flask的app.config配置對(duì)象的from_object()方法來直接導(dǎo)入。配置對(duì)象可以通過對(duì)象名從config字典中選出。一旦應(yīng)用程序被創(chuàng)建且配置好,擴(kuò)展就可以被初始化。調(diào)用擴(kuò)展里的init_app()之前先創(chuàng)建并完成初始化工作。

示例7-3. app/ _init__.py:應(yīng)用程序包構(gòu)造函數(shù)_

from flask import Flask, render_template 
from flask.ext.bootstrap import Bootstrap 
from flask.ext.mail import Mail
from flask.ext.moment import Moment
from flask.ext.sqlalchemy import SQLAlchemy 
from config import config

bootstrap = Bootstrap()
mail = Mail()
moment = Moment()
db = SQLAlchemy()

def create_app(config_name):
    app = Flask(__name__) 
    app.config.from_object(config[config_name]) 
    config[config_name].init_app(app)
    
    bootstrap.init_app(app)
    mail.init_app(app)
    moment.init_app(app)
    db.init_app(app)

    # attach routes and custom error pages here
    
    return app

工廠函數(shù)返回創(chuàng)建的應(yīng)用程序?qū)嵗?,但是?qǐng)注意,在當(dāng)前狀態(tài)下使用工廠函數(shù)創(chuàng)建的應(yīng)用程序是不完整的,因?yàn)樗鼈儧]有路由和自定義錯(cuò)誤頁面處理程序。這是下一節(jié)的主題。

3.2、在藍(lán)圖中實(shí)現(xiàn)應(yīng)用程序的功能

應(yīng)用程序工廠的轉(zhuǎn)化工作引出了路由的復(fù)雜化。在單腳本應(yīng)用中,應(yīng)用程序?qū)嵗侨值模钥梢院苋菀椎厥褂?b>app.route裝飾器定義路由。但是現(xiàn)在應(yīng)用程序在運(yùn)行時(shí)創(chuàng)建,app.route裝飾器只有在create_app()調(diào)用后才開始存在,這就太遲了。就像路由那樣,這些通過app.errorhandler裝飾器定義的自定義錯(cuò)誤頁面處理程序也存在同樣的問題。

幸運(yùn)的是Flask使用藍(lán)圖來提供一個(gè)更好的解決方案。一個(gè)藍(lán)圖就類似于一個(gè)可以定義路由的應(yīng)用程序。不同的是,和路由相關(guān)聯(lián)的藍(lán)圖都在休眠狀態(tài),只有當(dāng)藍(lán)圖在應(yīng)用中被注冊(cè)后,此時(shí)的路由才會(huì)成為它的一部分。使用定義在全局作用域下的藍(lán)圖,定義應(yīng)用程序的路由就幾乎可以和單腳本應(yīng)用程序一樣簡單了。

和應(yīng)用程序一樣,藍(lán)圖可以定義在一個(gè)文件或一個(gè)包中與多個(gè)模塊一起創(chuàng)建更結(jié)構(gòu)化的方式。為了追求最大的靈活性,可以在應(yīng)用程序包中創(chuàng)建子包來持有藍(lán)圖。示例7-4展示了創(chuàng)建藍(lán)圖的構(gòu)造函數(shù)。

示例7-4. app/main/ _init__.py:創(chuàng)建藍(lán)圖_

from flask import Blueprint

main = Blueprint("main", __name__) 

from . import views, errors

藍(lán)圖是通過實(shí)例化Blueprint類對(duì)象來創(chuàng)建的。這個(gè)類的構(gòu)造函數(shù)接收兩個(gè)參數(shù):藍(lán)圖名和藍(lán)圖所在的模塊或包的位置。與應(yīng)用程序一樣,在大多數(shù)情況下,對(duì)于第二個(gè)參數(shù)值使用Python的__name__變量是正確的。

應(yīng)用程序的路由都保存在app/main/views.py模塊內(nèi)部,而錯(cuò)誤處理程序則保存在app/main/errors.py中。導(dǎo)入這些模塊可以使路由、錯(cuò)誤處理與藍(lán)圖相關(guān)聯(lián)。重要的是要注意,在app/init.py腳本的底部導(dǎo)入模塊要避免循環(huán)依賴,因?yàn)?b>view.py和errors.py都需要導(dǎo)入main藍(lán)圖。

藍(lán)圖和應(yīng)用程序一樣注冊(cè)在create_app()工廠函數(shù)中,如示例7-5所示。

示例7-5. app/ _init__.py:藍(lán)圖注冊(cè)_

def create_app(config_name): 
    # ...
    from .main import main as main_blueprint 
    app.register_blueprint(main_blueprint)

    return app

示例7-6展示了錯(cuò)誤處理。

示例7-6. app/main/errors.py:藍(lán)圖的錯(cuò)誤處理

from flask import render_template 
from . import main

@main.app_errorhandler(404) 
def page_not_found(e):
    return render_template("404.html"), 404

@main.app_errorhandler(500) 
def internal_server_error(e):
    return render_template("500.html"), 500

在藍(lán)圖中寫錯(cuò)誤處理的不同之處是,如果使用了errorhandler裝飾器,則只會(huì)調(diào)用在藍(lán)圖中引起的錯(cuò)誤處理。而應(yīng)用程序范圍內(nèi)的錯(cuò)誤處理則必須使用app_errorhandler。

示例7-7展示了被更新在藍(lán)圖中的應(yīng)用程序路由。

示例7-7. app/main/views.py:帶有藍(lán)圖的應(yīng)用程序路由

from datetime import datetime
from flask import render_template, session, redirect, url_for

from . import main
from .forms import NameForm 
from .. import db
from ..models import User

@main.route("/", methods=["GET", "POST"]) 
def index():
    form = NameForm()
    if form.validate_on_submit():
        # ...
        return redirect(url_for(".index")) 
    return render_template("index.html",
                            form=form, name=session.get("name"),
                            known=session.get("known", False),
                            current_time=datetime.utcnow())

在藍(lán)圖中寫視圖函數(shù)有兩大不同點(diǎn)。第一,正如之前的錯(cuò)誤處理一樣,路由裝飾器來自于藍(lán)圖。第二個(gè)不同是url_for()函數(shù)的使用。你可能會(huì)回想,該函數(shù)的第一個(gè)參數(shù)為路由節(jié)點(diǎn)名,它給基于應(yīng)用程序的路由指定默認(rèn)視圖函數(shù)。例如,單腳本應(yīng)用程序中的index()視圖函數(shù)的URL可以通過url_for("index")來獲得。

不同的是Flask名稱空間適用于來自藍(lán)圖的所有節(jié)點(diǎn),這樣多個(gè)藍(lán)圖可以使用相同節(jié)點(diǎn)定義視圖函數(shù)而不會(huì)產(chǎn)生沖突。名稱空間就是藍(lán)圖名(Blueprint構(gòu)造函數(shù)中的第一個(gè)參數(shù)),所以index()視圖函數(shù)注冊(cè)為main.index且它的URL可以通過url_for("main.index")獲得。

在藍(lán)圖中,url_for()函數(shù)同樣支持更短格式的節(jié)點(diǎn),省略藍(lán)圖名,例如url_for(".index")。有了這個(gè),就可以這樣使用當(dāng)前請(qǐng)求的藍(lán)圖了。這實(shí)際意味著相同藍(lán)圖內(nèi)的重定向可以使用更短的形式,如果重定向跨藍(lán)圖則必須使用帶名稱空間的節(jié)點(diǎn)名。

完成了應(yīng)用程序頁面更改,表單對(duì)象也保存在app/main/forms.py模塊中的藍(lán)圖里面。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/45323.html

相關(guān)文章

  • Flask Web Development —— 大型應(yīng)用程序結(jié)構(gòu)(下)

    摘要:單元測試這個(gè)應(yīng)用非常小以至于不需要太多的測試,但是作為示例會(huì)在示例中展示兩個(gè)簡單的測試定義。示例單元測試編寫好的測試使用的是來自于標(biāo)準(zhǔn)庫中標(biāo)準(zhǔn)的包。為了運(yùn)行單元測試,可以在腳本中增加一個(gè)自定義的命令。 4、啟動(dòng)腳本 頂層目錄中的manage.py文件用于啟動(dòng)應(yīng)用。這個(gè)腳本會(huì)在示例7-8中展示。 示例7-8. manage.py:啟動(dòng)腳本 #!/usr/bin/env python im...

    whidy 評(píng)論0 收藏0
  • [分享] Flask 網(wǎng)絡(luò)開發(fā)經(jīng)典書籍: Flask Web Development

    摘要:他和妻子四個(gè)孩子兩只狗和一只貓共同生活在俄勒岡州波特蘭市。。還邀請(qǐng)他根據(jù)書的內(nèi)容,制作了兩個(gè)視頻教程。 showImg(http://img4.douban.com/lpic/s27205547.jpg); 這本書算是學(xué)習(xí)Flask的權(quán)威材料了,網(wǎng)上很多人都是推薦從這本書開始學(xué)習(xí)。起初,作者在自己的博客發(fā)布了一個(gè)大型的Flask建站教程,在這個(gè)教程大受歡迎的基礎(chǔ)上,才與OReilly公...

    HmyBmny 評(píng)論0 收藏0
  • Flask Web Development —— 基本應(yīng)用程序結(jié)構(gòu)

    摘要:注對(duì)于開發(fā)者來說,傳給應(yīng)用程序構(gòu)造函數(shù)的參數(shù)是比較容易弄混淆的。在應(yīng)程序中定義路由的最便捷的方式是通過顯示定義在應(yīng)用程序?qū)嵗系难b飾器,注冊(cè)被裝飾的函數(shù)來作為一個(gè)路由。一個(gè)常見的模式是使用裝飾器來注冊(cè)函數(shù)作為一個(gè)事件處理程序。 在這一章,你將學(xué)習(xí)Flask應(yīng)用程序不同部分。同時(shí)你將編寫和運(yùn)行你的第一個(gè)Flask web應(yīng)用程序。 1、初始化 在這章,你將學(xué)到Flask應(yīng)用程序的不...

    NusterCache 評(píng)論0 收藏0
  • Flask Web Development —— 模板(

    摘要:用真實(shí)的值替換變量并返回最終響應(yīng)字符串,這個(gè)過程稱為渲染。示例展示模板實(shí)現(xiàn)該響應(yīng)??刂平Y(jié)構(gòu)提供一些控制結(jié)構(gòu)用于改變模板流。這個(gè)示例展示如何使用循環(huán)做到這些同樣支持宏,這和代碼中的函數(shù)很像。 寫代碼最關(guān)鍵的是要易于維護(hù)且結(jié)構(gòu)清晰整潔。目前為止,你看到的例子都過于簡單從而沒有做這方面的要求。Flask視圖函數(shù)希望將兩個(gè)應(yīng)該完全獨(dú)立的任務(wù)一并處理,兩個(gè)任務(wù)有兩種代碼,一并處理勢(shì)必會(huì)引發(fā)問題。...

    fizz 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

chemzqm

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<