1. 程式人生 > 實用技巧 >Flask Turtoial(資料庫)

Flask Turtoial(資料庫)

Flask-SQLAlchemy關係型資料庫對映器 /ORM(全全稱Object Relation Mapping)

ORMs允許應用程式使用高階實體(類User,物件yang, 方法User.query.filter_by(username='xxx').first()),而不是表和SQL來管理資料庫.執行在物件的操作會被ORMs翻譯成資料庫命令,這意味著不需要使用SQL語言

models.py

from app import db


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))

    def __repr__(self):
        return '<User {}>'.format(self.username)

repr的作用

>>> u = User(username='susan', email='[email protected]')
>>> u
<User susan>
flask db init 生成migrations資料夾,對應有資料庫遷移的版本
flask db migrate -m "add users table"  # 生成遷移指令碼,但不對資料庫進行更改
flask db upgrade # 應用更改


如果想回退的話流程是:
flask db downgrade 回退修改
手動刪除對應的遷移指令碼

定義Post類

app/models.py

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    # 在一這一側定義relationship
    posts = db.relationship('Post', backref='author', lazy='dynamic')

    def __repr__(self):
        return '<User {}>'.format(self.username)


class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String(140))
    timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    user_id = db.Column(db.ForeignKey('user.id'))

    def __repr__(self):
        return '<Post {}>'.format(self.body)

Post類代表使用者撰寫的blog,timestamp可以提供給我們按時間檢索帖子的方法,因此預設defaut使用datetime.utcnow方法傳遞,而不是返回結果.

如何新增使用者? 比如叫john

python
>>> from app import db
>>> from app.models import User, Post
>>> u = User(username='john', email='[email protected]')
>>> db.session.add(u)
>>> db.session.commit()

如何查詢所有使用者?

>>> users = User.query.all()

>>> users
[<User john>, <User susan>]

>>> for u in users:
	    print(u.id , u.username)
	    
1 john
2 susan

當你知道使用者id的時候呢?如何查詢?

u = User.query.get(1)
>>> u

<User john>

新增一篇文章呢?

u = User.query.get(1)
p = Post(body='my first post!', author=u)
db.session.add(p)
db.session.cmmit()

由於我之前在User類中,定義過posts欄位,即db.relationship,

在關聯中,設定了一個虛擬的欄位author(backref=author),這樣我可使用(author=user)來生成post例項

其他

>>> # get all posts written by a user
>>> u = User.query.get(1)
>>> u
<User john>

# 這裡注意  u.posts方法使用的是dynamic查詢方法
>>> posts = u.posts.all()
>>> posts
[<Post my first post!>]
 
>>> # same, but with a user that has no posts
>>> u = User.query.get(2)
>>> u
<User susan>
>>> u.posts.all()
[]
 
>>> # print post author and body for all posts 
>>> posts = Post.query.all()
>>> for p in posts:
...     print(p.id, p.author.username, p.body)
...
1 john my first post!
 
# get all users in reverse alphabetical order
>>> User.query.order_by(User.username.desc()).all()
[<User susan>, <User john>]

刪除測試資料

>>> users = User.query.all()
>>> for u in users:
...     db.session.delete(u)
...
>>> posts = Post.query.all()
>>> for p in posts:
...     db.session.delete(p)
...
>>> db.session.commit()

Shell上下文

在python直譯器中,想要獲取app的物件,需要先import

而shell上下文可以直接啟動python直譯器,並匯入變數

只需要在microblog.py啟動檔案中寫入:

from app import app, db
from app.models import User, Post

@app.shell_context_processor
def make_shell_context():
    return {'db': db, 'User': User, 'Post': Post}

User有哪些欄位? Post有哪些欄位?哪些欄位需要索引? 那些需要唯一?外來鍵在那定義?外來鍵寫在哪? 需要放在Column裡面嗎?裡的值填什麼? relationship在哪定義?需要放在Column裡面嗎?寫法是什麼?

在Post欄位中的,欄位timestamp呼叫的是什麼方法? 什麼庫中的什麼? 是值還是方法? 為什麼要這麼呼叫?

@app.shell_context_processor 裝飾符為shell上下文註冊功能.

當flask shell執行的時候,呼叫此函式並註冊函式中的項