从零开始用 Flask 搭建一个网站(二)
從零開始用 Flask 搭建一個網站(一) 介紹了如何搭建 Python 環境,以及 Flask 應用基本項目結構。我們要搭建的網站是管理第三方集成的控制臺,類似于 Slack。 本篇主要講解數據如何在 Flask 應用中流動,其它的框架基本上也是大同小異。
數據庫
既然是數據的流動,首先要建立起存取數據的地方,也就是數據庫了(這里是指關系型數據庫,NoSQL 不在這討論)。第一節中我們使用了 Flask-SQLAlchemy 管理數據庫,在 Flask-SQLAlchemy 中,數據庫使用 URL 指定,最流行的數據庫 URL 格式如下:
| 數據庫引擎 | URL |
|---|---|
| MySQL | mysql://username:password@hostname/database |
| Postgres | postgresql://username:password@hostname/database |
| SQLite(Unix) | sqlite:absolute/path/to/database |
| SQLite(Windows) | sqlite:///c:/absolute/path/to/database |
在 config.py 中我們已經指定了數據庫 URL,如果使用云平臺部署程序,直接將生成的數據庫 URL 寫到 config.py 中 SQLALCHEMY_DATABASE_URI 即可。這里我們使用的是 SQLite 數據庫。Flask-SQLAlchemy 采用數據庫抽象層來操作數據庫,也稱為對象關系映射(Object-Relational Mapper, ORM),在用戶不知不覺的情況下把高層的面向對象操作轉換成低層的數據庫指令,因此易用性好。我們已經在 app/__init__.py 中實例化了 SQLAlchemy 類:
app/__init__.py
from flask_sqlalchemy import SQLAlchemy
...
db = SQLAlchemy()
... 定義模型
模型類可以理解為數據庫中的一張表,Flask-SQLAlchemy 提供了一個基類和一系列輔助類和函數來讓我們定義模型的結構。我們直接在 app 文件夾下創建一個 models.py 文件。鑒于每個網站需求都不一樣,所存的數據也不同,但本質上是大同小異的。這里以筆者網站需求為例,需要創建 Developer,Integration 和 Channel 三個表。
app/models.py 部分代碼
from flask import current_app
from app import dbclass Developer(db.Model): __tablename__ = 'developers' id = db.Column(db.Integer, primary_key=True) dev_key = db.Column(db.String(40), unique=True, index=True) platform = db.Column(db.String(50)) platform_id = db.Column(db.String(40), unique=True) username = db.Column(db.String(150), index=True) integrations = db.relationship('Integration', backref='developer') channels = db.relationship('Channel', backref='developer')class Integration(db.Model): __tablename__ = 'integrations' id = db.Column(db.Integer, primary_key=True) integration_id = db.Column(db.String(40), unique=True) name = db.Column(db.String(100)) description = db.Column(db.String(150)) icon = db.Column(db.String(150)) channel = db.Column(db.String(150)) token = db.Column(db.String(150)) developer_id = db.Column(db.Integer, db.ForeignKey('developers.id'))class Channel(db.Model): __tablename__ = 'channels' id = db.Column(db.Integer, primary_key=True) developer_id = db.Column(db.Integer, db.ForeignKey('developers.id')) channel = db.Column(db.String(150)) def __repr__(self): return '<Channel %r>' % self.channel 上面的每個 Class 都繼承了 Model 類,因此每個類在數據庫中都體現為一張表,表名用 __tablename__ 表示,一般用復數形式。這里主要講一下一對多的關系。可以看到上面 Developer 和 Integration 及 Channel 都有一個一對多的關系,一個用戶可以有多個集成及多個頻道。 看到這兩句:
integrations = db.relationship('Integration', backref='developer')
developer_id = db.Column(db.Integer, db.ForeignKey('developers.id')) 第一句表明添加到 Developer 表的 integrations 屬性表示這個關系的面向對象視角,對于一個 Developer 實例,integrations 屬性將返回與 Developer 相關的所有 Integration,db.relationship() 第一個參數表明關系的另一端是哪個模型,backref 參數向 Integration 添加一個 developer 屬性,從而定義反向關系。第二句是在 Integration 表中創建一個 developer_id 字段,這個字段被定義為外鍵,就是這個外鍵建立起了關系。傳給 db.ForeignKey() 的參數 'developers.id' 表明這列的值是 developers 表中行的 id 值。另外,__repr__() 方法返回一個具有可讀性的字符串表示模型,可以在調試和測試時使用。下面我們就在命令行中操作一下數據庫。
首先執行:
//創建 migrations 文件夾及相關文件
python manage.py db init 然后執行 :
//自動創建遷移腳本
python manage.py db migrate
//創建數據表或者升級到最新版本
python manage.py db upgrade 以后模型類有改動,比如刪除或添加列,都要執行這兩個命令,更新數據庫表。現在在項目目錄下應該自動生成了名為 dev 的數據庫。
接下來執行如下命令進入 Python Shell:
python manage.py shell 創建表
使用 db.create_all() 就可以根據模型類創建表。如圖:
使用 db.drop_all() 方法就可以刪除所有的表,但是這種方式比較粗暴,所有的數據也一同銷毀了。
插入行
以下命令在數據庫表中插入了一條數據:
通過數據庫會話 db.session 來管理對數據庫所做的改動,在準備把對象寫入數據庫之前,首先要添加到會話中,然后用 commit() 方法提交會話。接下來我們繼續插入一條 Integration 數據:
>>>from app.models import Integration,Channel
>>>integration = Integration(integration_id='i0001',name='github',description='first >>>application',channel='github_event',developer=developer)
>>> db.session.add(integration)
>>> db.session.commit() 注意上面的 developer 屬性,正是我們在 models.py 中 Developer 模型中定義的一對多關系 integrations 屬性的 backref 值, 所謂的反向關系即指在 Integration 表中每條數據都有一個 developer 屬性指向 Developer 表中的某條數據,這是一對多關系的高級表示。現在可以用 developer.integrations 來查看該 developer 擁有的哪些集成,運行截圖如下:
修改行
在提交數據庫會話之前,改變對象的某個屬性然后再提交即可更新行數據。如:
>>> developer.username = 'lisi'
>>> db.session.add(developer)
>>> db.session.commit() 運行截圖:
刪除行
調用 db.session.delete() 方法即可刪除行:
>>>db.session.delete(developer)
>>>db.session.commit() 查詢行
Flask-SQLAlchemy 為每個模型提供了 query 對象,最基本的查詢是返回表中的所有記錄:
>>>Developer.query.all() 使用過濾器可以進行更精確的查詢:
>>>Developer.query.filter_by(platform='qq').all() 如果你退出了 shell 會話,前面創建的對象就不會以 Python 對象的形式存在,而是作為各自數據庫表中的行。這時需要重數據庫中讀取行,再重新創建 Python 對象,如:
>>> new_developer = Developer.query.filter_by(dev_key=12345).first() 注意上面的 first() 方法,如果不加上,將返回一個 BaseQuery 對象,這樣就不能直接用 new_developer 來訪問它的屬性值。
在視圖函數中操作數據庫
上面介紹的所有數據庫操作可以直接在視圖函數中進行。假設我們要做一個簡陋的注冊功能,下面我們就來看看如何從網頁中獲取數據并保存在數據庫中。我們先定義一個用戶模型:
app/models.py
class User(db.model):__tablename__ = 'users'id = db.column(db.Integer, primary_key=True)username = db.column(db.String(50), unique=True)password = db.column(db.String(100))def __repr__(self):return '<User %r>' % self.username 然后在 main 文件夾下創建一個 forms.py 文件。
app/main/forms.py
from flask_wtf import Form
from wtforms import StringField, SubmitField, PasswordField
from wtforms.validators import DataRequiredclass UserForm(Form): username = StringField('Input your username', validators=[DataRequired()]) password = PasswordField('Input your password', validators=[DataRequired()]) submit = SubmitField('Submit') 我們使用了 flask-wtf 擴展(pip install flask-wtf)來處理表單。
然后我們用在 index 頁面中顯示這個表單。
index.html
{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}{% block title %}注冊{% endblock %}{% block content %}{% for message in get_flashed_messages() %} <div class="alert alert-warning"> <button type="button" class="close" data-dismiss="alert">×</button> {{ message }} </div>{% endfor %}<div id="form"><div class="col-md-4">{{ wtf.quick_form(form) }}</div></div>
{% endblock %} 現在回到 views.py 中,在我們的視圖函數中作如下改動:
app/main/views.py
...
from .forms import UserForm
from ..models import User
from app import db@main.route('/', methods=['GET', 'POST'])
def signin():form = UserForm()if form is None:flash('Should input username and password')elif form.validate_on_submit():user = User(username=form.username.data, password=form.password.data)db.session.add(user)try:db.session.commit()flash('User created !')except:db.session.rollback()flash('User create failed')return render_template('index.html', form=form) 接下來我們運行一下這個小試驗:
python manage.py runserver 總結
本節我們介紹了在 Flask 中是如何使用 Flask-SQLAlchemy 、Flask-Migrate來管理數據庫,并且示范了數據從網頁儲存到數據庫的過程,這只是最基礎的部分,下一節我們將探索如何在網頁上發送請求并且得到數據,以及如何在頁面之間傳遞數據。
作者:KenChoi - 極光
原文:從零開始用 Flask 搭建一個網站(二)
知乎專欄:極光日報
轉載于:https://www.cnblogs.com/jpush88/p/6697806.html
總結
以上是生活随笔為你收集整理的从零开始用 Flask 搭建一个网站(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 日出东方下一句是什么呢?
- 下一篇: “花低羞艳妓”下一句是什么