flask_sqlalchemy


簡介:python

flask_sqlalchemy 是 Flask Web 框架的一個擴展。

使 Web 服務器以 (ORM: Object Relational Mapping) 對象關係映射的方式與數據庫交互。mysql

1、安裝 flask_sqlalchemysql

shell > pip install Flask-SQLAlchemy

shell > ipython

import flask_sqlalchemy

print(flask_sqlalchemy.__version__)
2.1

# 若是沒有報錯,那就是安裝成功了。

2、配置 flask_sqlalchemy 鏈接數據庫shell

# app.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True

# app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://tmp:9898@192.168.1.40/tmp_db?charset=utf8"
# app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True

db = SQLAlchemy(app)


@app.route("/")
def index():
    return "Hello World"

if __name__ == "__main__":
    db.create_all()
    app.run(debug=True)

# 上面註釋掉的兩行代碼使用的數據庫類型爲 Mysql,鏈接數據的驅動是 PyMySQL (pip install PyMySQL)
# 若是是 Python 2.x,那麼驅動多是 MySQLdb,而不是 PyMySQL

# 啓動這個 APP 的時候,會實例化一個對象 db,而且將該 app 註冊到了 db 中,而後 db.create_all() 表明生成數據表 (雖然這裏沒有建立表)。

3、建立表數據庫

# app.py

class User(db.Model):
    """user 用戶表"""

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(32), unique=True, nullable=False)
    address = db.Column(db.String(128))

    def __init__(self):
        self.name = self.address = ""

    def __repr__(self):
        return "<Name: %r>" % self.name
        
# 重啓服務器,而後去數據庫中查看,就會多了一張名爲 user 的表,且有三個字段 id, name, address

# 因此說,ORM 中一張表就對應一個 Python class !

4、增、查、更、刪flask

# ipython

from app import db, User

一、增服務器

u = User()
u.name = "小王"
u.address = "BJ"

db.session.add(u)
db.session.commit()
db.session.close()

# 實例化一個對象,而後給該對象的屬性賦值,最後將該對象添加到數據庫會話中,提交事務,關閉會話便可!

# 這樣就新增了一條數據到數據庫中了。

二、查session

print(User.query.all())

# 查找 user 表中全部數據,注意:返回的是一個對象的列表

print(User.query.first())

# 查詢 user 表中第一條數據,絕不意外也是個對象

print(User.query.filter_by(id=1).first())
print(User.query.filter_by(id=1, name="小王").first())

# 查詢 id 等於 1 的數據,只顯示第一條。多個條件也是能夠的。但格式只能是 key=value 的方式,多條件關係爲 and。

print(User.query.filter(User.id == 1).first())
print(User.query.filter(User.id == 1, User.name == "小王").first())

# 先注意一下 filter 與 filter_by 參數寫法上的區別。
# 另外再注意一下:filter 是 不 支 持 x and x 或者 x or x 這樣的操做的,雖然這樣寫不報錯...

# filter 支持的操做是 > < = != 這些,固然還有上面 filter_by 的那種關係 x, y -> x and y。

# 那要用這種 and、or 怎麼辦 ?

from sqlalchemy import and_, or_

print(User.query.filter(and_(User.id == 1, User.address == "BJ")).first())
print(User.query.filter(or_(User.id == 1, User.address == "SH")).first())

# 對,就這麼搞

print(User.query.filter_by(id=1).value("name"))
print(list(User.query.filter_by(id=2).values("name", "address")))

# 輸出匹配數據的指定字段,默認是 select * form xxx,如今是 select name, address from xxx。
# 又要注意了:.value 只能用於找到的對象是一個時,例如找到多個對象,則 .value 只返回第一個對象的值。

from sqlalchemy import desc

print(User.query.order_by(User.id).all())
print(User.query.order_by(desc(User.id)).all())

# 以 User.id 升序、降序排列

print(User.query.limit(10).all()) == "limit 10" == "limit 0, 10"
print(User.query.limit(10).offset(5).all()) == "limit 5, 10"
print(User.query.slice(0, 10).all()) == "limit 0, 10"

# 這不是 limit 麼,從 offset 取,取 limit 條

# 腦經急轉彎:何時 0 等於 1 ?
# 答案:limit 的時候!( limit 0, 10 實際上是從第一條開始取十條 ) PS:還有 list index !

三、更app

*
u = User.query.filter_by(id=1).first()
u.name = "天王"

db.session.add(u)
db.session.commit()
db.session.close()

**
User.query.filter_by(id=2).update({"name": "地虎", "address": "SH"})

db.session.commit()
db.session.close()

# 兩種更新方法都在這裏啦!

四、刪框架

u = User.query.filter_by(id=1).first()

db.session.delete(u)
db.session.commit()
db.session.close()

# 完事!

5、一對多

# app.py

class User(db.Model):
    """user 用戶表"""

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(32), unique=True, nullable=False)
    address = db.Column(db.String(128))

    def __init__(self):
        self.name = self.address = ""

    def __repr__(self):
        return "<Name: %r>" % self.name


class Article(db.Model):
    """article 文章表"""
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(64), nullable=False)
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
    
    def __init__(self):
        self.title = ""
        
    def __repr__(self):
        return "<Title: %r>" % self.title

# 建立了兩張表 user、article,且 article 表的 author_id 字段經過外鍵關聯到了 user 表的 id 字段!

# 好了,關係已經創建,標準的一對多(一個做者對應多篇文章)

# ipython

from app import db, User, Article

print(User.query.all())
[<Name: '小王'>, <Name: '大王'>]

print(Article.query.all())
[<Title: 'flask 學習筆記'>, <Title: '敢問路在何方'>, <Title: 'python 從入門到精通'>]

# 經過上面學到的技能,新增了兩個用戶、三篇文章

# 需求1:看看 "敢問路在何方" 的做者是誰?

article = Article.query.filter_by(title="敢問路在何方").first()
user = User.query.filter_by(id=at.author_id).first()

print(user.name)

# 需求2:看看 "小王" 寫了哪些文章?

uid = User.query.filter_by(name="小王").first()
article_list = Article.query.filter_by(author_id=uid).all()

for obj in article_list:
    print(obj.title)

# 有沒有更方便的方法呢 ?有

# app

class Article(db.Model):
    """article 文章表"""

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(64), nullable=False)
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)

    user = db.relationship("User", backref="articles")

    def __init__(self):
        self.title = ""

    def __repr__(self):
        return "<Title: %r>" % self.title

# 只需給 Article 類加一個屬性便可。注意:user 並非一個存在的字段,而是一個屬性!
# 該屬性關聯到了 User 類,backref 指定反向引用的名稱爲 articles,即 User 表訪問這個屬性就能夠找到該用戶的全部文章!

from app import db, User, Article

# 需求1:

article = Article.query.filter_by(title="敢問路在何方").first()

print(article.user.name)

# 需求2:

user = User.query.filter_by(name="小王").first()

for obj in user.articles:
    print(obj.title)
    
# 方便不?只查詢一張表便可!

6、多對多

# app.py

article_tag = db.Table(
    "article_tag",
    db.Column("article_id", db.Integer, db.ForeignKey("article.id"), primary_key=True),
    db.Column("tag_id", db.Integer,db.ForeignKey("tag.id"), primary_key=True)
)

# 多對多關係須要創建一箇中間表,你看建表的方式跟原來的還不同!
# 表名,字段,類型 須要跟外鍵關聯的字段類型一致,外鍵 關聯到哪張表的哪一個字段,主鍵

class Article(db.Model):
    """article 文章表"""

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(64), nullable=False)
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)

    user = db.relationship("User", backref="articles")
    tags = db.relationship("Tag", secondary="article_tag", backref="articles")

    def __init__(self):
        self.title = ""

    def __repr__(self):
        return "<Title: %r>" % self.title

# 又加了一個屬性 tags,多了一個參數 secondary 關鍵字指向中間表

class Tag(db.Model):
    """tag 標籤表"""

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(32), unique=True, nullable=False)

    def __init__(self):
        self.name = ""

    def __repr__(self):
        return "<Name: %r>" % self.name
        
# 多了一張 tag 表,這就是張普通表,用來存儲標籤信息,有個隱藏屬性 articles 哦!

# 多對多:一篇文章有多個標籤,一個標籤又能標記給多篇文章

# ipython

from app import db, Article, Tag

t = Tag()
t.name = "python"

an = Article()
an.title = "python 數據分析"
an.author_id = 1
an.tags.append(t) or an.tags.append(Tag.query.filter_by(id=1).first())

db.session.add(t)
db.session.add(an)
db.session.commit()
db.session.close()

# 這就新加了一個標籤、一篇文章,且給這篇文章加了一個標籤

an = Article.query.filter_by(title="python 數據分析").first()

for obj in an.tags:
    print(obj.name)

# 這樣就查到了這篇文章的全部標籤

tn = Tag.query.filter_by(id=1).first()

for obj in tn.articles:
    print(obj.title)
    
# 這樣就查到了這個標籤的全部文章

# End

# 好了,這就是 flask_sqlalchemy 的鏈接方式、基本增、刪、改、查、一對多、多對多的一些文字!所有代碼以下:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True

# app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://tmp:9898@192.168.1.40/tmp_db?charset=utf8"
# app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True

db = SQLAlchemy(app)

article_tag = db.Table(
    "article_tag",
    db.Column("article_id", db.Integer, db.ForeignKey("article.id"), primary_key=True),
    db.Column("tag_id", db.Integer,db.ForeignKey("tag.id"), primary_key=True)
)


class User(db.Model):
    """user 用戶表"""

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(32), unique=True, nullable=False)
    address = db.Column(db.String(128))

    def __init__(self):
        self.name = self.address = ""

    def __repr__(self):
        return "<Name: %r>" % self.name


class Article(db.Model):
    """article 文章表"""

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(64), nullable=False)
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)

    user = db.relationship("User", backref="articles")
    tags = db.relationship("Tag", secondary="article_tag", backref="articles")

    def __init__(self):
        self.title = ""

    def __repr__(self):
        return "<Title: %r>" % self.title


class Tag(db.Model):
    """tag 標籤表"""

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(32), unique=True, nullable=False)

    def __init__(self):
        self.name = ""

    def __repr__(self):
        return "<Name: %r>" % self.name


@app.route("/")
def index():
    return "Hello World"

if __name__ == "__main__":
    db.create_all()
    app.run(debug=True)
View Code
相關文章
相關標籤/搜索