筆者以前未接觸過 Python,只是略懂一點前端,因此說從零開始也相差無幾吧。Flask 是一個輕量級的基於 Python 的框架,可是擴展性很是良好(Github 上 22000 多個 star 就知道羣衆的選擇不無道理),其餘的這裏就很少提了,下面就開始咱們的網站搭建之路。html
首先須要準備 Python 開發環境,這裏推薦使用 pyenv 來安裝和管理 Python。筆者使用的是 Mac OSX(自帶 Python 2.6),直接使用以下命令安裝 pyenv:前端
brew install pyenv
以後要升級 pyenv 的話就用:python
brew upgrade pyenv
安裝完之後,須要配置環境變量,若是使用 zsh,須要在 ~/.zshrc 加入如下代碼:git
export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" export PATH=$PATH:/sbin/ eval "$(pyenv init -)"
若是使用 bash,在 ~/.bash_profile 中加入便可。保存後重啓終端便可。
若是要安裝 Python 3.5.2,能夠用github
pyenv install 3.5.2
查看安裝的 Python 版本:sql
pyenv versions
切換局部 Python 環境(這裏通常指在 Application 文件夾下切換環境)shell
pyenv local 3.5.2
關於其餘更多命令,能夠參考 Command.md數據庫
這裏筆者推薦使用 PyCharm 來進行 python 項目開發。下載安裝後(這裏筆者下載的是 Professional 版本),新建一個 Flask 項目,而後指定目錄、python 環境:flask
完成後點擊 Create,這樣就建立了一個 Flask 項目,若是沒有安裝 Flask,PyCharm 會自動下載安裝。若是想使用 virtualenv,能夠參考下一個步驟。瀏覽器
使用虛擬環境能夠方便地安裝 Flask 並且能夠在系統的 Python 解釋器中避免包的混亂和版本的衝突。Python 3.3之後原生支持虛擬環境,命令爲 pyvenv。可使用以下命令建立虛擬環境(進入剛纔建立的 Flask 項目文件夾):
pyvenv venv
若是使用 Python 2.7或者如下版本,可使用第三方工具 virtualenv 建立虛擬環境:
sudo easy_install virtualenv
以上命令就能夠安裝 virtualenv(若是沒有安裝 easy_install,須要手動安裝,而 pyvenv 已經自帶 pip 和 easy_install)。下一步使用 virtualenv 命令在文件夾中建立 Python 虛擬環境:
virtualenv venv
完成後,會在 Flask 項目下生成 venv 文件夾。在使用虛擬環境以前,要先使用(pyvenv 和 virtualenv 建立的虛擬環境是同樣的,所以如下命令都可使用):
source venv/bin/activate
來激活,若是要退出虛擬環境,可使用:
deactivate
建立的虛擬環境會自動安裝 pip 和 easy_install,接下來可使用:
pip install flask
接下來就能夠在 Flask 中開始自由地遨(入)遊(坑)啦!
在介紹 Flask 的程序結構以前,先來看看標準 Flask 項目的項目結構(筆者覺得從宏觀到微觀的方式能夠更快的瞭解一個東西)。使用 PyCharm 新建 Flask 項目後,項目結構以下圖所示:
只有三個文件夾(venv 文件夾已經用命令行生成了)和一個簡單的入口類,接下來要把項目結構改形成標準的 Flask 項目結構:
Flask 項目有4個頂級文件夾:
同時還有一些文件:
雖然新建的 Flask Project 已經能夠運行,可是咱們仍是要按照標準的 Flask 程序來改造項目結構。下面咱們就來改造一下 TestProject。
在命令行中依次使用如下命令來安裝 Flask 擴展:
pip install flask-script pip install flask-sqlalchemy pip install flask-migrate
flask-script 能夠自定義命令行命令,用來啓動程序或其它任務;flask-sqlalchemy 用來管理數據庫的工具,支持多種數據庫後臺;flask-migrate 是數據庫遷移工具,該工具命令集成到 flask-script 中,方便在命令行中進行操做。
而後建立 config.py 文件,內容以下:
config.py
import os basedir = os.path.abspath(os.path.dirname(__file__)) class config: SECRET_KEY = os.environ.get('SECRET_KEY') or 'this is a secret string' SQLALCHEMY_TRACK_MODIFICATIONS = True @staticmethod def init_app(app): pass class DevelopmentConfig(config): DEBUG = True SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \ 'sqlite:///' + os.path.join(basedir, 'dev') class TestingConfig(config): TESTING = True SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \ 'sqlite:///' + os.path.join(basedir, 'test') 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 顧名思義,保存了一些配置變量。SQLALCHEMY_DATABASE_URI 變量在不一樣的配置中被賦予了不一樣的值,這樣就能夠在不一樣的環境中切換數據庫。若是是遠程數據庫則從環境變量中讀取 URL,不然在本地路徑中建立。
接下來建立一個 app 文件夾,並在此文件夾中建立一個 __init__.py 文件(init 先後都有兩個下劃線):
app/__init__.py
from flask import Flask from flask_sqlalchemy import SQLAlchemy from config import config db = SQLAlchemy() def create_app(config_name): app = Flask(__name__) app.config.from_object(config[config_name]) config[config_name].init_app(app) db.init_app(app) //此處缺省了部分代碼,後面會加上 return app
create_app() 就是程序的工廠函數,參數就是配置類的名字,即 config.py,其中保存的配置可使用 from_object() 方法導入。
接下來要解釋兩個重要的概念——路由和視圖函數。客戶端把請求發給 Web 服務器,Web 服務器再把請求發給 Flask 程序實例,Flask 程序實例須要知道每一個 URL 請求要運行哪些代碼,因此保存了一個 URL 到 Python 函數的映射關係。處理 URL 和函數之間關係的程序稱爲路由,這個函數稱爲視圖函數。例如:
@app.route('/') def index(): return '<h1>Hello World</h1>'
這裏使用 app.route 修飾器來定義路由,app 指 Flask 程序實例對象,後面能夠看到使用藍本管理路由後,由藍本實例對象來取代 app。Flask 使用藍原本定義路由,在藍本中定義的路由處於休眠狀態,直到藍本註冊到程序上後,路由真正成爲程序的一部分。藍本一般使用結構化的方式保存在包的多個模塊中。接下來在 app 文件夾下建立一個子文件夾 main,並在 main 中建立 __init__.py(若是使用 PyCharm,這裏有個快捷方式,右鍵點擊 app 文件夾,在菜單中選擇 new -> Python Package,在彈出的對話框中填寫包名而後確認便可):
app/main/__ init__.py
from flask import Blueprint //實例化 Blueprint 類,兩個參數分別爲藍本的名字和藍本所在包或模塊,第二個一般填 __name__ 便可 main = Blueprint('main', __name__) from . import views, errors
最後引用了兩個文件,之因此寫在最後是由於避免循環導入依賴,由於接下來在 main 文件夾下 建立的 views.py 和 errors.py 都要導入藍本 main。
app/main/views.py
from flask import render_template //導入藍本 main from . import main @main.route('/') def index(): return render_template('index.html')
在以前路由的概念解釋中,index 函數直接返回了 HTML 字符串(一般不這麼作),這裏則使用了 render_templete() 函數來渲染 index.html,並返回。Flask 使用了 Jinja2 引擎來渲染模板,模板文件都放在 templates 文件夾下,而且只能命名爲 templates,不然 Jinja2 會拋出 TemplageNotFound 異常。因爲咱們的app 是一個 Python Package(在目錄中包含 init.py 默認成爲 Python Package),因此須要將 templates 放在 app 目錄下。在 app 下 中建立名爲 templates 的文件夾,在 PyCharm 中右鍵點擊該文件夾,而後選擇 Make Directory As -> Template Folder,如圖:
接下來在 templates 下新建一個 index.html 和 404.html 模板:
app/templates/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> <h1>Hello World</h1> </body> </html>
app/templates/404.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Not Found</title> </head> <body> <h1>Can't find request page!</h1> </body> </html>
以後會講解模板的具體用法,如今接着來定義 errors.py:
app/main/errors.py
from flask import render_template from . import main @main.app_errorhandler(404) def page_not_found(e): return render_template('404.html'), 404
上面的步驟是讓程序的路由保存在 views.py 中,而錯誤處理交給 errors.py,這兩個模塊已經和藍本 main 關聯起來了(在藍本中導入了這兩個模塊),如今須要在工廠函數中註冊藍本 main。將以下代碼加入到上面缺省代碼中便可:
app/__init__.py
def create_app(config_name): #... from .main import main as main_blueprint app.register_blueprint(main_blueprint) return app
最後兩個步驟是建立 requirements.txt 以及啓動腳本 manage.py。程序中必須包含一個 requirements.txt 文件,用於記錄全部的依賴包和版本號,便於在其它電腦上建立相同的開發環境。直接在終端使用以下命令便可建立 requirements.txt 文件:
pip freeze > requirements.txt
之後安裝了新的依賴包或者升級版本後,從新執行該命令便可更新 requirements.txt 文件。若是要手動添加也能夠,在 PyCharm 中用 Command + , 喚出 Preferences 對話框,而後選擇 Project -> Project Interpreter 便可查看全部的依賴包及其版本號(還有最新版本號提示),如圖:
若是要在另外一臺電腦上建立這個虛擬環境的徹底副本,運行如下命令便可:
pip install -r requirements.txt
最後建立啓動腳本 manage.py:
manage.py
import os from app import create_app, db from flask_script import Manager, Shell from flask_migrate import Migrate, MigrateCommand app = create_app(os.getenv('FLASK_CONFIG') or 'default') manager = Manager(app) migrate = Migrate(app, db) def make_shell_context(): return dict(app=app, db=db) manager.add_command("shell",Shell(make_context=make_shell_context)) manager.add_command('db', MigrateCommand) if __name__ == '__main__': manager.run()
這個腳本首先建立程序,而後增長了兩個命令:shell 和 db,咱們以後能夠在命令行中直接使用。
到此爲止,咱們的目錄結構以下:
如今就來啓動咱們的程序,在命令行中進入 TestProject 目錄,而後執行以下命令便可運行:
python manage.py runserver
命令行運行截圖以下:
Flask 默認的本機地址爲:http://127.0.0.1:5000/ ,如今用瀏覽器打開這個地址,應該能夠看到以下頁面:
到這一步,咱們的第一個 Flask 程序已經完成了!雖然尚未創建數據庫,頁面也很是糟糕,可是以後咱們會一步步進行完善!
本文參考書籍 Flask Web 開發:基於 Python 的 Web 應用開發實戰(做者: Miguel Grinberg)
做者:KenChoi - 極光
原文:從零開始用 Flask 搭建一個網站(一)
知乎專欄:極光日報