從零開始用 Flask 搭建一個網站(一)

前言

筆者以前未接觸過 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數據庫

使用 IDE

這裏筆者推薦使用 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 的程序結構以前,先來看看標準 Flask 項目的項目結構(筆者覺得從宏觀到微觀的方式能夠更快的瞭解一個東西)。使用 PyCharm 新建 Flask 項目後,項目結構以下圖所示:

只有三個文件夾(venv 文件夾已經用命令行生成了)和一個簡單的入口類,接下來要把項目結構改形成標準的 Flask 項目結構:

Flask 項目有4個頂級文件夾:

  • app ——(本例中是 jbox)Flask 程序保存在此文件夾中
  • migrations ——包含數據庫遷移腳本(安裝了 flask-migrate 後自動生成)
  • tests ——單元測試放在此文件夾下
  • venv ——Python 虛擬環境

同時還有一些文件:

  • requirements.txt —— 列出了全部的依賴包,以便於在其餘電腦中從新生成相同的環境
  • config.py 存儲配置
  • manage.py 啓動程序或者其餘任務
  • gun.conf Gunicorn 配置文件

雖然新建的 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 搭建一個網站(一)
知乎專欄:極光日報

相關文章
相關標籤/搜索