Flask 專案實戰教程。。。
阿新 • • 發佈:2018-12-30
flask 不僅簡介小巧,同時運用的時候十分靈活。下面簡單介紹一下如何編寫一個 flask專案。涉及呼叫開發伺服器,資料庫連線以及 ORM 對映,還有資料庫的遷移,模板使用。後期再完善會話,管理後臺,快取等。
一 安裝環境
我們使用 flask web框架,並用 sqlalchemy來做資料庫對映,並使用 migrate做資料遷移。
二 建立專案
flask 沒有 django 那樣原生的 manage管理工具(flask-admin可以實現,日後再說)。因此我們需要手動建立目錄。新建一個 myproject目錄,在裡面建 app tmp兩個資料夾,然後在 app資料夾裡面建立 static, templates 兩個資料夾,用來儲存靜態檔案和模板。最後目錄結構如下:
.
├── app
│ ├── static
│ ├── templates
└── tmp
三 初始化檔案
建立一些檔案,在 app檔案裡建立 __init__.py models.py views.py 然後在與app 同目錄下建立 config.py 和 run.py 此時的目錄結構如下:
(env) [email protected]:~/project/python/flask/project$ tree
.
├── app
│ ├── static
│ ├── templates
│ ├── __init__.py
│ ├── models.py
│ ├── views.py
├── config.py
├── run.py
└── tmp
四 開始專案
1 hello wrod
開啟 (/app/__init.py) 檔案,寫入
注意,我們的 app 資料夾其實是一個python包,from app import views 這句話也就是從 包app裡面匯入 views模組,所以寫成註釋的那句話也沒錯,其他程式碼實踐喜歡寫成後面那種
現在我們來開始寫我們的檢視,開啟 (/app/views.py)
下一步我們將要啟動我們的開發伺服器,開啟 (/run.py)
這段程式碼需要注意第一句 from app import app。也許會有疑問,我們的 app 包裡,貌似沒有 app.py 這樣的模組。其實這是 flask 方式和python的匯入方式。from app 指匯入 app 包裡的 __iniy__.py 所以這句話的含義是匯入 __.init__.py 裡面的 app例項。
開啟shell 執行
用瀏覽器開啟 http://127.0.0.1:5000/ 將會看到一個輸入 hello world 的頁面
2 連線資料庫
下面開始連線資料庫引擎 先要做一個簡單的配置 開啟 (/config.py)
然後開啟 (/app/__init__.py)
開啟 (/app/models.py)
我們的模型建立了一個 user類,正好是 資料庫裡面的 user 表,表有四個欄位
現在我們的資料庫配置已經好了,可是還沒有建立資料庫。新建一個檔案 (/db_create.py)
這個指令碼是完全通用的,所有的應用路徑名都是從配置檔案讀取的。當你用在自己的專案時,你可以把指令碼拷貝到你的專案目錄下就能正常使用了。
執行這條命令之後,你就建立了一個新的app.db檔案。這是個支援遷移的空sqlite資料庫,同時也會生成一個帶有幾個檔案的db_repository目錄,這是SQLAlchemy-migrate儲存資料庫檔案的地方,注意如果資料庫已存在它就不會再重新生成了。這將幫助我們在丟失了現有的資料庫後,再次自動創建出來。
執行
或者使用 sqlite 圖形化客戶端,沒有需要安裝 (windows 下直接下載安裝包即可)
3 資料庫遷移
每當我們更改了 models 。等價於更改了資料庫的表結構,這個時候,需要資料庫同步。新建 (/db_mirgate.py)
這個指令碼看起來很複雜,SQLAlchemy-migrate通過對比資料庫的結構(從app.db檔案讀取)和models結構(從app/models.py檔案讀取)的方式來建立遷移任務,兩者之間的差異將作為一個遷移指令碼記錄在遷移庫中,遷移指令碼知道如何應用或者撤銷一次遷移,所以它可以方便的升級或者降級一個數據庫的格式。
開始資料庫遷移
$ python db_mirgate.py
New migration saved as db_repository/versions/001_migration.py Current database version: 1
相應的,我們繼續建立資料庫 升級和回退的指令碼
(/db_upgrade)
(/db_downgrade.py)
4 操作資料庫
接下來,我們定義一個新的models class 並做第二次遷移歸併
開啟(/app/models.py)
這裡我們進行了兩個class 的關聯。
開啟 (/app/views.py)
這次我們使用了模板, 新建(/app/templates/user.html)
用瀏覽器訪問 http://127.0.0.1:5000/adduser/username/useremail
最後還可以用 sqlite 客戶端開啟檢視我們的資料庫變換。關於更多的資料庫操作方法,請閱讀 sqlalchemy文件。
最後我們的程式碼目錄結構如下:
(env)[email protected]:~/project/python/flask/project$ tree
.
├── app
│ ├── __init__.py
│ ├── models.py
│ ├── static
│ ├── templates
│ │ ├── 404.html
│ │ ├── 500.html
│ │ ├── index.html
│ │ └── user.html
│ ├── views.py
├── app.db
├── config.py
├── db_create.py
├── db_downgrade.py
├── db_migrate.py
├── db_repository
│ ├── __init__.py
│ ├── manage.py
│ ├── migrate.cfg
│ ├── README
│ └── versions
│ ├── 001_migration.py
│ ├── 002_migration.py
│ ├── __init__.py
├── db_upgrade.py
├── requirements.txt
├── run.py
├── tmp
程式碼下載: https://github.com/rsj217/flask-extend/tree/master/project
一 安裝環境
我們使用 flask web框架,並用 sqlalchemy來做資料庫對映,並使用 migrate做資料遷移。
$ pip install flask
$ pip install SQLAlchemy==0.7.9
$ pip install flask-sqlalchemy
$ pip install flask-migrate
二 建立專案
flask 沒有 django 那樣原生的 manage管理工具(flask-admin可以實現,日後再說)。因此我們需要手動建立目錄。新建一個 myproject目錄,在裡面建 app tmp兩個資料夾,然後在 app資料夾裡面建立 static, templates 兩個資料夾,用來儲存靜態檔案和模板。最後目錄結構如下:
.
├── app
│ ├── static
│ ├── templates
└── tmp
三 初始化檔案
建立一些檔案,在 app檔案裡建立 __init__.py models.py views.py 然後在與app 同目錄下建立 config.py 和 run.py 此時的目錄結構如下:
(env)
.
├── app
│ ├── static
│ ├── templates
│ ├── __init__.py
│ ├── models.py
│ ├── views.py
├── config.py
├── run.py
└── tmp
四 開始專案
1 hello wrod
開啟 (/app/__init.py) 檔案,寫入
# -*- coding: utf-8 -*- from flask import Flask # 引入 flask app = Flask(__name__) # 例項化一個flask 物件 import views # 匯入 views 模組 # from app import views
注意,我們的 app 資料夾其實是一個python包,from app import views 這句話也就是從 包app裡面匯入 views模組,所以寫成註釋的那句話也沒錯,其他程式碼實踐喜歡寫成後面那種
現在我們來開始寫我們的檢視,開啟 (/app/views.py)
# -*- coding: utf-8 -*-
from app import app
from models import User, Post, ROLE_USER, ROLE_ADMIN
@app.route('/')
def index():
return 'hello world, hello flask'
下一步我們將要啟動我們的開發伺服器,開啟 (/run.py)
# -*- coding: utf-8 -*- from app import app if __name__ == '__main__': app.debug = True # 設定除錯模式,生產模式的時候要關掉debug app.run() # 啟動伺服器
這段程式碼需要注意第一句 from app import app。也許會有疑問,我們的 app 包裡,貌似沒有 app.py 這樣的模組。其實這是 flask 方式和python的匯入方式。from app 指匯入 app 包裡的 __iniy__.py 所以這句話的含義是匯入 __.init__.py 裡面的 app例項。
開啟shell 執行
$ python run.py
(env)[email protected]:~/project/python/flask/project$ python run.py
* Running on http://127.0.0.1:5000/
* Restarting with reloader
用瀏覽器開啟 http://127.0.0.1:5000/ 將會看到一個輸入 hello world 的頁面
2 連線資料庫
下面開始連線資料庫引擎 先要做一個簡單的配置 開啟 (/config.py)
# -*- coding: utf-8 -*-
import os
basedir = os.path.abspath(os.path.dirname(__file__))
SQLALCHEMY_DATABASE_URI = 'sqlite:///%s' % os.path.join(basedir, 'app.db')
SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository')
CSRF_ENABLED = True
SECRET_KEY = 'you-will-never-guess'
然後開啟 (/app/__init__.py)
# -*- coding: utf-8 -*-
import os
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from config import basedir
app = Flask(__name__)
app.config.from_object('config') # 載入配置檔案
db = SQLAlchemy(app) # 初始化 db 物件
# from app import views, models # 引用檢視和模型
import views, models
開啟 (/app/models.py)
# -*- coding: utf-8 -*-
from app import db
ROLE_USER = 0
ROLE_ADMIN = 1
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
nickname=db.Column(db.String(60), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
role = db.Column(db.SmallInteger, default=ROLE_USER)
def __repr__(self):
return '<User %r>' % self.nickname
我們的模型建立了一個 user類,正好是 資料庫裡面的 user 表,表有四個欄位
現在我們的資料庫配置已經好了,可是還沒有建立資料庫。新建一個檔案 (/db_create.py)
# -*- coding: utf-8 -*-
from migrate.versioning import api
from config import SQLALCHEMY_DATABASE_URI
from config import SQLALCHEMY_MIGRATE_REPO
from app import db
import os.path
db.create_all()
if not os.path.exists(SQLALCHEMY_MIGRATE_REPO):
api.create(SQLALCHEMY_MIGRATE_REPO, 'database repository')
api.version_control(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
else:
api.version_control(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO, api.version(SQLALCHEMY_MIGRATE_REPO))
這個指令碼是完全通用的,所有的應用路徑名都是從配置檔案讀取的。當你用在自己的專案時,你可以把指令碼拷貝到你的專案目錄下就能正常使用了。
開啟shell 執行
$ python db_create_db
執行這條命令之後,你就建立了一個新的app.db檔案。這是個支援遷移的空sqlite資料庫,同時也會生成一個帶有幾個檔案的db_repository目錄,這是SQLAlchemy-migrate儲存資料庫檔案的地方,注意如果資料庫已存在它就不會再重新生成了。這將幫助我們在丟失了現有的資料庫後,再次自動創建出來。
執行
slqite3 app.db
>>> .tables
>>> user
或者使用 sqlite 圖形化客戶端,沒有需要安裝 (windows 下直接下載安裝包即可)
$ sudo apt-get install sqlitebrowser
3 資料庫遷移
每當我們更改了 models 。等價於更改了資料庫的表結構,這個時候,需要資料庫同步。新建 (/db_mirgate.py)
# -*- coding: utf-8 -*-
import imp
from migrate.versioning import api
from app import db
from config import SQLALCHEMY_DATABASE_URI
from config import SQLALCHEMY_MIGRATE_REPO
migration = SQLALCHEMY_MIGRATE_REPO + '/versions/%03d_migration.py' % (api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO) + 1)
tmp_module = imp.new_module('old_model')
old_model = api.create_model(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
exec old_model in tmp_module.__dict__
script = api.make_update_script_for_model(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO, tmp_module.meta, db.metadata)
open(migration, "wt").write(script)
api.upgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
print 'New migration saved as ' + migration
print 'Current database version: ' + str(api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO))
這個指令碼看起來很複雜,SQLAlchemy-migrate通過對比資料庫的結構(從app.db檔案讀取)和models結構(從app/models.py檔案讀取)的方式來建立遷移任務,兩者之間的差異將作為一個遷移指令碼記錄在遷移庫中,遷移指令碼知道如何應用或者撤銷一次遷移,所以它可以方便的升級或者降級一個數據庫的格式。
開始資料庫遷移
$ python db_mirgate.py
New migration saved as db_repository/versions/001_migration.py Current database version: 1
相應的,我們繼續建立資料庫 升級和回退的指令碼
(/db_upgrade)
# -*- coding: utf-8 -*-
from migrate.versioning import api
from config import SQLALCHEMY_DATABASE_URI
from config import SQLALCHEMY_MIGRATE_REPO
api.upgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
print 'Current database version: ' + str(api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO))
(/db_downgrade.py)
# -*- coding: utf-8 -*-
from migrate.versioning import api
from config import SQLALCHEMY_DATABASE_URI
from config import SQLALCHEMY_MIGRATE_REPO
v = api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
api.downgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO, v - 1)
print 'Current database version: ' + str(api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO))
4 操作資料庫
接下來,我們定義一個新的models class 並做第二次遷移歸併
開啟(/app/models.py)
# -*- coding: utf-8 -*-
from app import db
ROLE_USER = 0
ROLE_ADMIN = 1
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
nickname=db.Column(db.String(60), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
role = db.Column(db.SmallInteger, default=ROLE_USER)
posts = db.relationship('Post', backref = 'author', lazy = 'dynamic')
def __repr__(self):
return '<User %r>' % self.nickname
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
def __repr__(self):
return '<Post %r>' % (self.body)
這裡我們進行了兩個class 的關聯。
$ python db_mirgrate.py
New migration saved as db_repository/versions/002_migration.py Current database version: 2
開啟 (/app/views.py)
# -*- coding: utf-8 -*-
from flask import render_template, flash, redirect, session, url_for, request, g
from app import app, db
from models import User, Post, ROLE_USER, ROLE_ADMIN
@app.route('/')
def index():
return render_template('index.html')
@app.route('/adduser/<nickname>/<email>')
def adduser(nickname, email):
u = User(nickname=nickname, email=email)
try:
db.session.add(u)
db.session.commit()
return 'add successful'
except Exception, e:
return 'something go wrong'
@app.route('/getuser/<nickname>')
def getuser(nickname):
user = User.query.filter_by(nickname=nickname).first()
return render_template('user.html', user=user)
@app.errorhandler(404)
def internal_error(error):
return render_template('404.html'), 404
@app.errorhandler(500)
def internal_error(error):
db.session.rollback()
return render_template('500.html'), 500
這次我們使用了模板, 新建(/app/templates/user.html)
<html>
<head>
<title>user</title>
</head>
<body>
<h1>user</h1>
<ul>
<li>user: {{ user.nickname }}</li>
<li>email: {{ user.email }}</li>
</ul>
</body>
</html>
最後執行
$ python run.py
用瀏覽器訪問 http://127.0.0.1:5000/adduser/username/useremail
最後還可以用 sqlite 客戶端開啟檢視我們的資料庫變換。關於更多的資料庫操作方法,請閱讀 sqlalchemy文件。
最後我們的程式碼目錄結構如下:
(env)[email protected]:~/project/python/flask/project$ tree
.
├── app
│ ├── __init__.py
│ ├── models.py
│ ├── static
│ ├── templates
│ │ ├── 404.html
│ │ ├── 500.html
│ │ ├── index.html
│ │ └── user.html
│ ├── views.py
├── app.db
├── config.py
├── db_create.py
├── db_downgrade.py
├── db_migrate.py
├── db_repository
│ ├── __init__.py
│ ├── manage.py
│ ├── migrate.cfg
│ ├── README
│ └── versions
│ ├── 001_migration.py
│ ├── 002_migration.py
│ ├── __init__.py
├── db_upgrade.py
├── requirements.txt
├── run.py
├── tmp
程式碼下載: https://github.com/rsj217/flask-extend/tree/master/project