首先在环境中导入包
pip install flask-sqlalchemy
1.ORM模型与表的映射
对象关系映射(Object Relationship Mapping),简称ORM,是一种可以用Python面向对象的方式来操作关系型数据库的技术,具有可以映射到数据库表能力的 Python类我们称之为ORM模型。一个ORM模型与数据库中一个表相对应,ORM模型中的每个类属性分别对应表的每个字段,ORM模型的每个实例对象对应表中每条记录。ORM技术提供了面向对象与SQL交互的桥梁,让开发者用面向对象的方式操作数据库,使用ORM模型具有以下优势。
- 开发效率高:几乎不需要写原生SQL语句,使用纯 Python的方式操作数据库,大大的提高了开发效率。
- 安全性高:ORM模型底层代码对一些常见的安全问题,比如sQL注入做了防护,比直接使用SQL语句更加安全。
- 灵活性强:Flask-SQLAlchemy底层支持SQLite、MySQL、Oracle、PostgreSQL等关系型数据库,但针对不同的数据库,ORM 模型代码几乎一模一样,只需修改少量代码,即可完成底层数据库的更换。-
以下我们用Flask-SQLAlchemy来创建一个User模型,示例代码如下
# flask 直接在代码里面创建表,下面创建表对象
class User(db.Model):
__tablename__ = "user" # 表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 创建属性,类型为integer,设为主键,自增
username = db.Column(db.String(100), nullable=False) # valchar(100), 非空
password = db.Column(db.String(100), nullable=False) # valchar(100), 非空
通过方法将数据同步到数据库中
# 把表同步到数据库中去
db.create_all() # 有问题
遇到问题,同样是报RuntimeError: Working outside of application context.
解决方案就是手动的放到app.context()中
# 把表同步到数据库中去
with app.app_context():
db.create_all()
运行结果:
所有代码:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
# mysql主机名
HOSTNAME = "127.0.0.1"
# 端口号
PORT = 3306
# 账号
USERNAME = "root"
# 密码
PASSWORD = 1234
# 数据库名
DATABASE = "database_learn"
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8'
db = SQLAlchemy(app)
# 测试连接
with app.app_context():
with db.engine.connect() as conn:
rs = conn.execute(text("select 1"))
print(rs.fetchone())
@app.route("/")
def hello():
return "hello"
# flask 直接在代码里面创建表,下面创建表对象
class User(db.Model):
__tablename__ = "user" # 表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 创建属性,类型为integer,设为主键,自增
username = db.Column(db.String(100), nullable=False) # valchar(100), 非空
password = db.Column(db.String(100), nullable=False) # valchar(100), 非空
# 创建一条数据
# 对应sql:insert user(username,password) values("法外狂徒","1234")
# user = User(username="法外狂徒", password="1234")
# 把表同步到数据库中去
with app.app_context():
db.create_all()
# 当前文件做为主入口运行
if __name__ == '__main__':
app.run()
2.ORM模型的CRUD操作
首先要有表对象类
class User(db.Model):
__tablename__ = "user" # 表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 创建属性,类型为integer,设为主键,自增
username = db.Column(db.String(100), nullable=False) # valchar(100), 非空
password = db.Column(db.String(100), nullable=False) # valchar(100), 非空
添加数据的方法:
# 添加数据
@app.route("/add")
def add_user():
# 1.创建ORM对象
user = User(username="wtf", password="1234")
# 2.将对象添加到session会话中
db.session.add(user)
# 3.提交会话
db.session.commit()
return "用户添加成功!"
查询数据的方法有两种:
# 查找数据
@app.route("/query")
def query_user():
# 1.get请求查找,通过id,主键查找
user = User.query.get(1)
print(f'根据主键为1查到的用户姓名是:{user.username}---密码是{user.password}')
# 2,通过filter_by,传入属性查找
user2 = User.query.filter_by(username="wtf")
print(type(user2)) # <class 'flask_sqlalchemy.query.Query'>query类型类似于数组,能够进行切片
for user3 in user2:
print(user3.username+"-----------"+user3.password)
return "数据查找成功!"
修改数据的方法:
# 修改数据
@app.route("/update")
def update_user():
# 1 查找
user2 = User.query.filter_by(username="wtf")[0]
# 2 修改
user2.password = "1111"
# 3 同步
db.session.commit() # 同步带数据库当中
return "数据修改成功!"
删除数据的方法:
# 删除数据
@app.route("/delete")
def delete_user():
# 1 查找
user = User.query.get(1)
# 2 删除
db.session.delete(user)
# 3 同步数据库
db.session.commit()
return "数据删除成功!"
程序所有代码:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
# mysql主机名
HOSTNAME = "127.0.0.1"
# 端口号
PORT = 3306
# 账号
USERNAME = "root"
# 密码
PASSWORD = 1234
# 数据库名
DATABASE = "database_learn"
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8'
db = SQLAlchemy(app)
@app.route("/")
def hello():
return "主页"
# flask 直接在代码里面创建表,下面创建表对象
class User(db.Model):
__tablename__ = "user" # 表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 创建属性,类型为integer,设为主键,自增
username = db.Column(db.String(100), nullable=False) # valchar(100), 非空
password = db.Column(db.String(100), nullable=False) # valchar(100), 非空
# 添加数据
@app.route("/add")
def add_user():
# 1.创建ORM对象
user = User(username="wtf", password="1234")
# 2.将对象添加到session会话中
db.session.add(user)
# 3.提交会话
db.session.commit()
return "用户添加成功!"
# 查找数据
@app.route("/query")
def query_user():
# 1.get请求查找,通过id,主键查找
user = User.query.get(1)
print(f'根据主键为1查到的用户姓名是:{user.username}---密码是{user.password}')
# 2,通过filter_by,传入属性查找
user2 = User.query.filter_by(username="wtf")
print(type(user2)) # <class 'flask_sqlalchemy.query.Query'>query类型类似于数组,能够进行切片
for user3 in user2:
print(user3.username+"-----------"+user3.password)
return "数据查找成功!"
# 修改数据
@app.route("/update")
def update_user():
# 1 查找
user2 = User.query.filter_by(username="wtf")[0]
# 2 修改
user2.password = "1111"
# 3 同步
db.session.commit() # 同步带数据库当中
return "数据修改成功!"
# 删除数据
@app.route("/delete")
def delete_user():
# 1 查找
user = User.query.get(1)
# 2 删除
db.session.delete(user)
# 3 同步数据库
db.session.commit()
return "数据删除成功!"
# 当前文件做为主入口运行
if __name__ == '__main__':
app.run()
3.ORM模型外键与表的关系
外键
外键是数据库层面的技术,在Flask-SQLAIchemy中支持创建ORM模型的时候就指定外键,
创建外键是通过db.ForeignKey实现的。
比如这里我们创建一个Article表,这个表有一个author id字段,通过外键引用_user表的 id字段,用来保存文章是由谁编写的,那么Article的模型代码如下:
class Article(db.Model):
__tablename__ = "article " # 表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 创建属性,类型为integer,设为主键,自增
title = db.Column(db.String(100), nullable=False) # valchar(100), 非空
content = db.Column(db.Text, nullable=False) # 内容
# 添加外键
author_id = db.Column(db.Intrger, db.ForeigenKey("user.id"))
relationship
通常我们就可以通过author_id来获得作者名
但是一点都不智能,所以可以用relationship来,通过外键直接访问需要的数据
class Article(db.Model):
__tablename__ = "article" # 表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 创建属性,类型为integer,设为主键,自增
title = db.Column(db.String(100), nullable=False) # valchar(100), 非空
content = db.Column(db.Text, nullable=False) # 内容
# 添加外键
author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
# 自动的帮你做的事情就是 author = User.query.get(author_id)
author = db.relationship("User", back_populates="articles") # 通过查找外键,就看是否有和User相关的表
# author = db.relationship("User", backref="articles") # 不需要对暗号
同时在引用端也要进行添加,这样的效果就是能够通过查询articles属性,直接访问作者相对应书籍的对象
class User(db.Model):
__tablename__ = "user" # 表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 创建属性,类型为integer,设为主键,自增
username = db.Column(db.String(100), nullable=False) # valchar(100), 非空
password = db.Column(db.String(100), nullable=False) # valchar(100), 非空
articles = db.relationship("Article", back_populates="author")
测试
先在书籍里面添加数据
# 添加数据
@app.route("/add/books")
def add_books():
# 1.创建ORM对象
article1 = Article(title="Flask学习", content="flask学习,学不明白!")
article2 = Article(title="Django学习", content="Django学习,学不明白!")
author = User.query.get(2)
article1.author = author
article2.author = author
# 2.将对象添加到session会话中
db.session.add_all([article1, article2])
# 3.提交会话
db.session.commit()
return "书籍添加成功!"
查询书籍数据,能够同时查询到对应的作者的全部信息
@app.route("/query/books")
def query_books():
article = Article.query.get(3)
print(f"书名:{article.title},作者名:{article.author.username},密码:{article.author.password},内容:{article.content}")
return "书籍查询成功!"
运行结果:
书名:Flask学习,作者名:wtf,密码:1234,内容:flask学习,学不明白!
作者也能通过外键,查询到它对应的所有书籍的全部信息
@app.route("/query/userbooks")
def query_userbooks():
author = User.query.get(2)
for i in author.articles:
print(i.title+"\t"+i.content)
return "作者所写的数据查询成功!"
运行结果:
Flask学习 flask学习,学不明白!
Django学习 Django学习,学不明白!
所有代码:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
# mysql主机名
HOSTNAME = "127.0.0.1"
# 端口号
PORT = 3306
# 账号
USERNAME = "root"
# 密码
PASSWORD = 1234
# 数据库名
DATABASE = "database_learn"
app = Flask(__name__)
app.config[
'SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8'
db = SQLAlchemy(app)
@app.route("/")
def hello():
return "主页"
# flask 直接在代码里面创建表,下面创建表对象
class User(db.Model):
__tablename__ = "user" # 表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 创建属性,类型为integer,设为主键,自增
username = db.Column(db.String(100), nullable=False) # valchar(100), 非空
password = db.Column(db.String(100), nullable=False) # valchar(100), 非空
articles = db.relationship("Article", back_populates="author")
class Article(db.Model):
__tablename__ = "article" # 表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 创建属性,类型为integer,设为主键,自增
title = db.Column(db.String(100), nullable=False) # valchar(100), 非空
content = db.Column(db.Text, nullable=False) # 内容
# 添加外键
author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
# 自动的帮你做的事情就是 author = User.query.get(author_id)
author = db.relationship("User", back_populates="articles") # 通过查找外键,就看是否有和User相关的表
# author = db.relationship("User", backref="articles") # 不需要对暗号
with app.app_context():
db.create_all()
# 添加数据
@app.route("/add/books")
def add_books():
# 1.创建ORM对象
article1 = Article(title="Flask学习", content="flask学习,学不明白!")
article2 = Article(title="Django学习", content="Django学习,学不明白!")
author = User.query.get(2)
article1.author = author
article2.author = author
# 2.将对象添加到session会话中
db.session.add_all([article1, article2])
# 3.提交会话
db.session.commit()
return "书籍添加成功!"
@app.route("/query/books")
def query_books():
article = Article.query.get(3)
print(f"书名:{article.title},作者名:{article.author.username},密码:{article.author.password},内容:{article.content}")
return "书籍查询成功!"
@app.route("/query/userbooks")
def query_userbooks():
author = User.query.get(2)
for i in author.articles:
print(i.title+"\t"+i.content)
return "作者所写的数据查询成功!"
# 添加数据
@app.route("/add")
def add_user():
# 1.创建ORM对象
user = User(username="wtf", password="1234")
# 2.将对象添加到session会话中
db.session.add(user)
# 3.提交会话
db.session.commit()
return "用户添加成功!"
# 查找数据
@app.route("/query")
def query_user():
# 1.get请求查找,通过id,主键查找
user = User.query.get(1)
print(f'根据主键为1查到的用户姓名是:{user.username}---密码是{user.password}')
# 2,通过filter_by,传入属性查找
user2 = User.query.filter_by(username="wtf")
print(type(user2)) # <class 'flask_sqlalchemy.query.Query'>query类型类似于数组,能够进行切片
for user3 in user2:
print(user3.username + "-----------" + user3.password)
return "数据查找成功!"
# 修改数据
@app.route("/update")
def update_user():
# 1 查找
user2 = User.query.filter_by(username="wtf")[0]
# 2 修改
user2.password = "1111"
# 3 同步
db.session.commit() # 同步带数据库当中
return "数据修改成功!"
# 删除数据
@app.route("/delete")
def delete_user():
# 1 查找
user = User.query.get(1)
# 2 删除
db.session.delete(user)
# 3 同步数据库
db.session.commit()
return "数据删除成功!"
# 当前文件做为主入口运行
if __name__ == '__main__':
app.run()