Python---Flask--04--SQLAlchemy

大多數的數據庫引擎都有對應的 Python 包,包括開源包和商業包。Flask 並不限制你使用何種類型的數據庫包,所以能夠根據本身的喜愛選擇使用 MySQL、Postgres、SQLite、Redis、MongoDB 或者 CouchDB。html

若是這些都沒法知足需求,還有一些數據庫抽象層代碼包供選擇,例如 SQLAlchemy 和MongoEngine。你可使用這些抽象包直接處理高等級的 Python 對象,而不用處理如表、文檔或查詢語言此類的數據庫實體。mysql

使用Flask-SQLAlchemy管理數據庫

安裝

pip install flask-sqlalchemysql

基本使用

FLask-SQLAlchemy數據庫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|數據庫

配置

from flask.ext.sqlalchemy import SQLAlchemy
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =\
 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
db = SQLAlchemy(app)

db 對象是 SQLAlchemy 類的實例,表示程序使用的數據庫,同時還得到了 Flask-SQLAlchemy提供的全部功能。flask

定義模型

from app import db
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin


class User(db.Model, UserMixin):
    __tablename = 'user'  #表名稱

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100), unique=True)
    email = db.Column(db.String(100), unique=True)
    password = db.Column(db.String(100))
    add_time = db.Column(db.DateTime, default=datetime.now)
    state = db.Column(db.Integer, default=1, comment='狀態 1--有效 0--無效')

    def __repr__(self):
        return '<User %r>'% self.username
    # @property
    # def password(self):
    #     raise AttributeError('password not read')
    #
    # @password.setter
    # def password(self,password):
    #     self.password = generate_password_hash(password)


    def verify_password(self,pwd):
        """驗證密碼是否正確"""
        return check_password_hash(self.password, pwd)

類變量 tablename 定義在數據庫中使用的表名。若是沒有定義 tablename,Flask-SQLAlchemy 會使用一個默認名字,但默認的表名沒有遵照使用複數形式進行命名的約定,因此最好由咱們本身來指定表名。其他的類變量都是該模型的屬性,被定義爲 db.Column類的實例。
db.Column 類構造函數的第一個參數是數據庫列和模型屬性的類型。列出了一些可用的列類型以及在模型中使用的 Python 類型。
|類型|Python中的類型|說明|
|---|---|---|
|Integer|Int|整形|
|SmallInteger|int|短整型|
|BigInteger|ing或者long|不限長度|
|Float|float|浮點型|
|Numeric|decimal|定點數|
|String|str|字符串|
|Text|str|文本|
|DateTime|datetime.datetime|日期和時間|
|Date|datetime.date|日期|
|Time|datetime.time|時間|
|Boolean|bool|布爾|
|Enum|str|枚舉|
|Interval|datetime.timedelta|時間間隔|session

db.Column中其他參數指定屬性的配置選項:
|選項名|說明 |
|---|---|
|primary_key|若是設置爲True,則是主鍵|
|unique|若是設置爲True,這列不容許出現重複|
|index| 若是設置爲True,爲這列建立索引,提示查詢效率|
|nullable| 若是設置爲True, 這列容許使用空值,若是設爲Fasle,這列不容許使用空值
|default|爲這列設置默認值|app

關係

關係型數據庫使用關係把不一樣表中的行聯繫起來。表示用戶和角色之間的一種簡單關係。這是角色到用戶的一對多關係,由於一個角色可屬於多個用戶,而每一個用戶都只能有一個角色。
一對多關係在模型類中的表示方法如示例所示:函數

class Role(db.Model):
 # ...
    users = db.relationship('User', backref='role')

class User(db.Model):
 # ...
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

關係使用 users 表中的外鍵鏈接了兩行。添加到 User 模型中的 role_id 列被定義爲外鍵,就是這個外鍵創建起了關係。傳給 db.ForeignKey() 的參數 'roles.id' 代表,這列的值是 roles 表中行的 id 值。post

添加到 Role 模型中的 users 屬性表明這個關係的面向對象視角。對於一個 Role 類的實例, users 屬性將返回與角色相關聯的用戶組成的列表。db.relationship() 的第一個參數代表這個關係的另外一端是哪一個模型。若是模型類還沒有定義,可以使用字符串形式指定。url

db.relationship() 中的 backref 參數向 User 模型中添加一個 role 屬性,從而定義反向關係。這一屬性可替代 role_id 訪問 Role 模型,此時獲取的是模型對象,而不是外鍵的值。

大多數狀況下,db.relationship() 都能自行找到關係中的外鍵,但有時卻沒法決定把哪一列做爲外鍵。例如,若是 User 模型中有兩個或以上的列定義爲 Role 模型的外鍵,SQLAlchemy 就不知道該使用哪列。若是沒法決定外鍵,你就要爲 db.relationship() 提供額外參數,從而肯定所用外鍵。表 列出了定義關係時經常使用的配置選項。
表 經常使用的SQLAlchemy關係選項
|選項名| 說  明|
|---|---|
|backref| 在關係的另外一個模型中添加反向引用|
|primaryjoin| 明確指定兩個模型之間使用的聯結條件。只在模棱兩可的關係中須要指定|
|lazy |指定如何加載相關記錄。可選值有 select(首次訪問時按需加載)、immediate(源對象加
載後就加載)、joined(加載記錄,但使用聯結)、subquery(當即加載,但使用子查詢),
noload(永不加載)和 dynamic(不加載記錄,但提供加載記錄的查詢)|
|uselist |若是設爲 Fales,不使用列表,而使用標量值|
|order_by |指定關係中記錄的排序方式|
|secondary| 指定多對多關係中關係表的名字|
|secondaryjoin| SQLAlchemy 沒法自行決定時,指定多對多關係中的二級聯結條件|

除了一對多以外,還有幾種其餘的關係類型。一對一關係能夠用前面介紹的一對多關係表示,但調用 db.relationship() 時要把 uselist 設爲 False,把「多」變成「一」。多對一關係也可以使用一對多表示,對調兩個表便可,或者把外鍵和 db.relationship() 都放在「多」這一側。最複雜的關係類型是多對多,須要用到第三張表,這個表稱爲關係表。

數據庫操做

添加

import db
user = User(username='',password='')
db.session.add(iser)
dn.session.commit()

更新

import db
user = User.query.get(id)
user.name='aaaaaaa'
db.session.commit()

刪除

import db
user.User.query.get(id)
db.session.delete(user)
db.session.commit()

查詢

query.all() 獲取所有
query.filter() 把過濾器添加到原查詢上,返回一個新的查詢
filter_by() 把等值過濾器添加到原查詢上,返回一個新的查詢
limit() 使用指定的值限制返回的結果數量,返回一個新的查詢
offset() 偏移原查詢返回的結果,返回一個新的結果
order_by 根據指定條件對原查詢結果進行排序,返回一個新查詢
group_by 根據指定條件對原查詢結果進行分組,返回一個新的查詢
first() 返回查詢的第一個結果,若是沒有返回None
first_or_404() 返回查詢的第一個結果,若是沒有結果返回404錯誤
get() 返回指定主鍵對應的行,若是沒有返回None
get_or_404() 返回指定主鍵對應的行,若是沒有找到對象,則終止請求,返回404錯誤
count() 返回查詢結果的數量
paginate() 返回一個Paginage對象,它包含指定範圍的結果

在視圖函數中操做數據庫

@home.route('/register', methods=['GET', 'POST'])
def register():
    """註冊"""
    form = RegisterForm()

    if form.validate_on_submit():
        data = form.data

        user = User(
            username=data['username'],
            password=generate_password_hash(data['password']),
            email=data['email']
        )
        db.session.add(user)
        db.session.commit()
        flash('註冊成功')
        return redirect(url_for('home.login'))

    return render_template('/home/user/register.html', form=form)
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息