搭建Flask-SQLAlchemy运行的基本环境
import os
import sys
import click
from flask import Flask
from flask_sqlalchemy import SQLAlchemy # 数据库依赖
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
# SQLite URI compatible
WIN = sys.platform.startswith('win')
if WIN:
prefix = 'sqlite:///'
else:
prefix = 'sqlite:////'
# 数据库设置
dev_db = prefix + os.path.join(basedir, 'data.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# app.config['SQLALCHEMY_ECHO'] = True # 输出SQL语句到控制台
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URI', dev_db)
db = SQLAlchemy(app)
@app.route('/')
def hello():
u = User.query.get(1)
print(u)
return 'Welcome to hello Hi!'
然后运行flask run
如果能正常打开,说明你的运行环境已经可以了,若是缺少Flask-SQLAlchemy
依赖包,请自行安装。
代码编辑好后,我们使用flask shell
命令来调试 例如flask dbinit
,每次运行都会删除并创建新的数据库和表,@app.cli.command()
装饰器表明这是一个flask shell
的命令行。
@app.cli.command()
def dbinit():
'''删除并重新构建数据库'''
click.echo('删除数据库和表')
db.drop_all()
click.echo("创建数据库!")
db.create_all()
click.echo("数据库创建成功!")
做好了以上的准备,就可以开始编写Model
代码了。
一对一关系
关系使用 relationship()
函数表示。然而外键必须用类 sqlalchemy.schema.ForeignKey
来单独声明.
这里的一对一关系使用User(用户基本资料)和UserData(用户的拓展资料),如果需要给用户的基本资料添加一写拓展资料,这种关系必须是一对一的关系。这里我们假设需要为用户添加一个邮件的拓展资料,分别定义用户User和UserData模型,并使用关系方法定义他们之间的一对一关系:
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32), unique=True)
userdata = db.relationship(
'UserData', uselist=False, back_populates='user')
class UserData(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(200))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship('User', back_populates=('userdata'))
uselist=False
标志指示在关系的“多”端放置标量属性而不是集合。将一对多转换为一对一,back_populates()
显示表明双方的对应关系,这种方法比较简单。编写测试代码:
@app.cli.command()
def test1to1():
'''一对一测试'''
print("开始测试")
user = User()
user.name = 'baby'
db.session.add(user)
db.session.commit()
userdata = UserData()
userdata.email = 'bosi@qq.com'
# userdata.user_id = user.id #建立关系方法1
userdata.user = user # 建立关系方法2
db.session.add(userdata)
db.session.commit()
print("添加{}成功!".format(user.userdata.email))
添加数据的代码很简单就不解释了。
userdata.user_id = user.id
和 userdata.user = user
是两种定义关系的添加数据的方法。
终端下运行: (base) ( ̄︶ ̄)↗ flask dbinit 删除数据库和表 创建数据库! 数据库创建成功! (base) ( ̄︶ ̄)↗ flask test1to1 开始测试 添加bosi@qq.com成功! (base) ( ̄︶ ̄)↗
我们可以看到上边的运行结果,在DBeaver中打开数据库,可以看到ER图如下:
一对多关系
一对多和一对一关系基本相似,去掉uselist=False
就可以了,这里使用了作者和文章的一对多关系,一个作者可以发表多篇文章。先定义模型和关系:
class Author(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32), unique=True)
articles = db.relationship(
'Article', back_populates='author')
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), unique=True)
author_id = db.Column(db.Integer, db.ForeignKey('author.id'))
author = db.relationship('Author', back_populates='articles')
back_populates
,这个属性非常好用哈,显示的定义了一对多关系。另外记得db.ForeignKey
绑定主键。我们编写代码测试一下:
@app.cli.command()
def test1tomore():
author = Author()
author.name = 'J.sky'
db.session.add(author)
db.session.commit()
ac1 = Article()
ac1.title = '一对一关系'
ac1.author_id = author.id # 建立关系方法1
ac2 = Article()
ac2.title = '多对多关系'
ac2.author = author # 建立关系方法2
ac3 = Article()
ac3.title = '添加append测试'
author.articles.append(ac3) # 建立关系方法3
db.session.add(ac1)
db.session.add(ac2)
db.session.commit()
for ar in author.articles:
print(ar.title)
运行代码测试:
(base) ( ̄︶ ̄)↗ flask dbinit
删除数据库和表
创建数据库!
数据库创建成功!
(base) ( ̄︶ ̄)↗ flask test1tomore
多对多关系
添加append测试
一对一关系
一对多有三种添加数据和定义关系的方法:
ac1.author_id = author.id # 建立关系方法1
ac2.author = author # 建立关系方法2
author.articles.append(ac3) # 建立关系方法3
多对多关系
如果您想要用多对多关系,您需要定义一个用于关系的辅助表。对于这个辅助表, 强烈建议 不 使用模型,而是采用一个实际的表。这里使用了Article
和Tag
之间的多对多关系,一个文章可以有多个标签,一个标签下也可以有多个文章。关系辅助表一定要在模型表之前定义,不然创建表的时候容易报错。先定义关系辅助表:
#关系表要放到表的前边建立
tags = db.Table('tags',
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
db.Column('article_id', db.Integer,
db.ForeignKey('article.id'))
接着Article
添加关系,定义tag
:
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), unique=True)
author_id = db.Column(db.Integer, db.ForeignKey('author.id'))
author = db.relationship('Author', back_populates='articles')
# 建立多对多关系
tags = db.relationship('Tag', secondary=tags, back_populates='articles')
class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(20), unique=True)
articles = db.relationship(
'Article', secondary=tags, back_populates='tags')
编写代码测试:
@app.cli.command()
def testmtom():
art1 = Article(title='我是王大锤')
art2 = Article(title='小狗露西很可爱')
art3 = Article(title='快乐的写代码')
tag1 = Tag(name='分类1')
tag2 = Tag(name='分类2')
tag1.articles.append(art1)
tag1.articles.append(art2)
tag2.articles.append(art2)
tag2.articles.append(art3)
db.session.add(art1)
db.session.add(art2)
db.session.add(art3)
db.session.add(tag1)
db.session.add(tag2)
db.session.commit()
for a in tag1.articles:
print(a.title)
for t in art2.tags:
print(t.name)
运行代码:
(base) ( ̄︶ ̄)↗ flask dbinit
删除数据库和表
创建数据库!
数据库创建成功!
(base) ( ̄︶ ̄)↗ flask testmtom
我是王大锤
小狗露西很可爱
分类1
分类2
完整代码请参考仓库里: