西宁软件优化网站建设,西安紧急通知,广告 网站举例,app下载安卓软件接口路由技术 一、Flask 简介1、环境安装#xff1a;2、一个最小的应用3、两种运行方式 二、定义路由1、普通路由2、动态路由3、限定类型4、地址尾部的“/” 三、请求与响应-请求方法四、请求与响应-处理请求数据1、request的常用属性/方法2、get 请求参数3、json 请求4、表单… 接口路由技术 一、Flask 简介1、环境安装2、一个最小的应用3、两种运行方式 二、定义路由1、普通路由2、动态路由3、限定类型4、地址尾部的“/” 三、请求与响应-请求方法四、请求与响应-处理请求数据1、request的常用属性/方法2、get 请求参数3、json 请求4、表单请求5、文件请求 五、请求与响应-处理响应信息1、文本型2、元组3、Json4、html5、额外数据 六、测试平台环境配置七、接口配置1、flask-restx 介绍2、插件安装3、demo 示例 八、接口使用1、设计框架的原则a、高耦合实例b、低内聚示例 2、编写 RESTFUL 风格的接口3、添加路由的方式方式一方式二 九、集成swagger1、namespace 的使用2、swagger 接口文档配置a、api.parser()用法b、get 请求示例c、post 请求示例1、处理 json 格式2、处理 files格式3、处理 form格式4、处理choice格式 十、orm介绍1、什么是持久化2、什么是 ORM3、ORM 与 SQL 的对比4、ORM 优缺点 十一、orm中间件配置十二、数据库与表管理创建表操作删除表操作 十三、对象与数据模型1、数据模型2、设计用户表字段3、Flask-SQLAlchemy 的属性字段定义4、Flask-SQLAlchemy 字段常用关键字参数5、Flask-SQLAlchemy 对象与数据模型示例 十四、数据CRUD1、添加数据createa、单条数据新增b、多条数据新增 2、读取数据reada、查询表中全部数据b、条件查询——单条件查询c、条件查询——多条件查询 3、修改数据update4、删除数据delete 十五、多表关系-一对多1、一对多关系2、一对多表结构3、一对多增删查改a、数据新增b、数据查询多查一一查多 c、数据修改一改多多改一 d、数据删除 一、Flask 简介
Flask 是一个轻量级的 web 开发框架。 它依赖 jinja2 和 Werkzeug WSGI 服务的一个微型框架。
1、环境安装
pip install flask
2、一个最小的应用
# 1. 导入 Flask 模块
from flask import Flask
# 2. 创建Flask应用程序实例
app Flask(__name__)# 3. 定义路由及视图函数
app.route(/)
def hello_world():return pHello, World!/p
# 4. 启动程序
if __name__ __main__:app.run()3、两种运行方式
linux/mac: 命令行运行 $ export FLASK_APPhello $ flask run windows: 命令运行 set FLASK_APPapp.py flask run 代码调用 if name ‘main’: app.run() 二、定义路由
1、普通路由
通过装饰器 app.route 添加路由
from flask import Flask#2、创建flask应用程序的实例__name____main__
appFlask(__name__)#添加路由
app.route(/)
def hello_world():return phello world/papp.route(/demo)
def demo():return phello world 666/p#启动入口
if __name____main__:#flask服务启动起来#轮询等待的方式等待浏览器发来请求#会一直接收请求直到程序停止app.run()2、动态路由
通过 app.route(/user/username) 添加动态路由
from flask import Flask#2、创建flask应用程序的实例__name____main__
appFlask(__name__)#添加路由
app.route(/)
def hello_world():return phello world/papp.route(/demo)
def demo():return phello world 666/papp.route(/userinfo/username)
def demo1(username):return fhello world 这是{username}同学#启动入口
if __name____main__:#flask服务启动起来#轮询等待的方式等待浏览器发来请求#会一直接收请求直到程序停止app.run()3、限定类型
路径中添加 类型变量名 来限定变量的类型 app.route(/post/int:post_id) string接收任何不包含斜杠的文本 int接收正整数 float接收正浮点数 path类似string但可以包含斜杠 uuid接收UUID字符串 #!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2023/5/26 07:03
# Author : 杜兰特
# File : flask_demo.py#1、导入flask模块
from log_utils import loggerfrom flask import Flask#2、创建flask应用程序的实例__name__ __main__
appFlask(__name__)#限定类型
app.route(/user/int:id)
def demo2(id):return fhello world 这是{id}app.route(/user/string:username)
def demo3(username):return fhello world 这是{username}同学#启动入口
if __name____main__:#flask服务启动起来#轮询等待的方式等待浏览器发来请求#会一直接收请求直到程序停止app.run()4、地址尾部的“/”
路由的尾部带有“/”浏览器的地址栏中输入和不输入“/”的效果一样
路由的尾部没有“/”输入的 URL 的结尾不能加“/”会报错
#1、导入flask模块
from flask import Flask#2、创建flask应用程序的实例__name__ __main__
appFlask(__name__)#添加路由
app.route(/demo)
def demo():return phello world 666/p#启动入口
if __name____main__:#flask服务启动起来#轮询等待的方式等待浏览器发来请求#会一直接收请求直到程序停止app.run() 三、请求与响应-请求方法
请求 说明 GET 获取服务器资源 POST 新增服务器资源 PUT 更新服务器资源客户端提供改变后的完整资源 DELETE 删除服务器资源 接口设计 查询get 新增post 修改put 删除delete #!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2023/5/27 00:01
# Author : 杜兰特
# File : http_request_demo.py
from flask import FlaskappFlask(__name__)#methods是列表类型可以添加多种请求方式。get、post、put、delete
app.route(/cases,methods[get])
def get_case():return {code:0,msg:get success}app.route(/cases,methods[post])
def post_case():return {code:0,msg:post success}app.route(/cases,methods[put])
def put_case():return {code:0,msg:put success}app.route(/cases,methods[delete])
def delete_case():return {code:0,msg:delete success}if __name__ __main__:app.run(debugTrue)四、请求与响应-处理请求数据
1、request的常用属性/方法
args记录请求中的查询参数 json记录请求中的json数据 files记录请求上传的文件 form记录请求中的表单数据 method记录请求使用的http方法 url记录请求的URL地址 host记录请求的域名 headers记录请求的头信息
2、get 请求参数
场景普通的 url 链接接收一个 get 请求 解决办法request.args
#需要导入request而不是requests
from flask import Flask,request
from log_utils import loggerappFlask(__name__)app.route(/login,methods[get])
def demo1():logger.info(f请求参数为{request.args})arequest.args.get(a)brequest.args.get(b)logger.info(fa的值为{a},b的值为{b})return {code:0,msg:get success}if __name__ __main__:app.run(debugTrue)127.0.0.1 - - [27/May/2023 09:03:29] GET /login HTTP/1.1 200 -
[2023-05-27 09:04:04] [INFO] [flask_param_demo.py]/[line: 17]/[demo1] 请求参数为ImmutableMultiDict([(a, 88), (b, 66)])
[2023-05-27 09:04:04] [INFO] [flask_param_demo.py]/[line: 20]/[demo1] a的值为88,b的值为66 3、json 请求
场景POST 相关的请求带有 json 数据格式 解决办法request.json
#需要导入request而不是requests
from flask import Flask,request
from log_utils import loggerappFlask(__name__)app.route(/register,methods[post])
def demo2():logger.info(f请求参数为{request.json})datarequest.json.get(time)logger.info(f时间为{data})return {code:0,msg:post success}if __name__ __main__:app.run(debugTrue)[2023-05-27 09:05:55] [INFO] [flask_param_demo.py]/[line: 26]/[demo2] 请求参数为{time: 2023-05-27, status: success}
[2023-05-27 09:05:55] [INFO] [flask_param_demo.py]/[line: 28]/[demo2] 时间为2023-05-27 4、表单请求
场景比如测试人网站的登录接口需要用户名和密码前端会提交一个 form 表单给后台 解决办法request.form
#需要导入request而不是requests
from flask import Flask,request
from log_utils import loggerappFlask(__name__)app.route(/register,methods[put])
def demo3():logger.info(f请求参数为{request.form})namerequest.form.get(name)passwordrequest.form.get(password)emailrequest.form.get(email)logger.info(f请求参数name为{name},password为{password}email为{email})return {code: 0, msg: put success}if __name__ __main__:app.run(debugTrue)[2023-05-27 09:07:42] [INFO] [flask_param_demo.py]/[line: 34]/[demo3] 请求参数为ImmutableMultiDict([(name, kobe), (password, 666666), (email, 77777)])
[2023-05-27 09:07:42] [INFO] [flask_param_demo.py]/[line: 38]/[demo3] 请求参数name为kobe,password为666666email为77777 5、文件请求
场景 页面上有个更新头像的功能 或者上传一个 excel 文件的功能 允许我们提交一个图片或者文件到后端服务器那么 解决方法 request.files.get(‘file’) 获取文件对象 filename 获取文件对象的文件名 save()方法 保存文件到指定路径下
#需要导入request而不是requests
from flask import Flask,request
from log_utils import loggerappFlask(__name__)app.route(/file,methods[post])
def demo4():logger.info(f请求方法为{request.method})logger.info(f请求url为{request.url})logger.info(f请求host为{request.host})logger.info(f请求headers为{request.headers})fileobjrequest.files.get(name)logger.info(ffileobj的值为{fileobj})logger.info(f文件名为{fileobj.filename})#保存文件fileobj.save(f./{fileobj.filename})return {code: 0, msg: file success}if __name__ __main__:app.run(debugTrue)[2023-05-27 09:10:10] [INFO] [flask_param_demo.py]/[line: 43]/[demo4] 请求方法为POST
[2023-05-27 09:10:10] [INFO] [flask_param_demo.py]/[line: 44]/[demo4] 请求url为http://127.0.0.1:5000/file
[2023-05-27 09:10:10] [INFO] [flask_param_demo.py]/[line: 45]/[demo4] 请求host为127.0.0.1:5000
[2023-05-27 09:10:10] [INFO] [flask_param_demo.py]/[line: 46]/[demo4] 请求headers为User-Agent: PostmanRuntime/7.32.2
Accept: */*
Postman-Token: 593d536e-4bbd-45a2-89be-d8670f66aa42
Host: 127.0.0.1:5000
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: multipart/form-data; boundary--------------------------624583842625202752710421
Content-Length: 10016[2023-05-27 09:10:10] [INFO] [flask_param_demo.py]/[line: 48]/[demo4] fileobj的值为FileStorage: 员工用车导入模板 (2).xlsx (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)
[2023-05-27 09:10:10] [INFO] [flask_param_demo.py]/[line: 49]/[demo4] 文件名为员工用车导入模板 (2).xlsx
127.0.0.1 - - [27/May/2023 09:10:10] POST /file HTTP/1.1 200 -
五、请求与响应-处理响应信息
1、文本型
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2023/5/27 09:27
# Author : 杜兰特
# File : http_response_demo.pyfrom flask import Flask
from flask import jsonify,render_template,make_responseappFlask(__name__)#返回文本
app.route(/text)
def demo():return 文本信息if __name__ __main__:app.run(debugTrue)2、元组
返回元组 (response, status) (response, headers) (response, status, headers) 响应状态码默认为 200
from flask import Flask
from flask import jsonify,render_template,make_responseappFlask(__name__)#返回元组
app.route(/tuple)
def tuple_res():return hello,200,{status: 0, type: success}if __name__ __main__:#host#port#debugTrue:热加载方便调试app.run(debugTrue)3、Json
直接返回 dict 会转换为 json 使用jsonify()方法通过参数传入键值对
from flask import Flask
from flask import jsonify,render_template,make_responseappFlask(__name__)#返回字典
app.route(/dict)
def get_dict_res():return {status:0}app.route(/json)
def get_json_res():#return jsonify({status:0})#或者return jsonify(status1,namekobe)if __name__ __main__:#host#port#debugTrue:热加载方便调试app.run(debugTrue)
4、html
使用模板渲染技术 html 文件必须在同级的 templates 目录下
from flask import Flask
from flask import jsonify,render_template,make_responseappFlask(__name__)app.route(/html)
def get_html():return render_template(demo.html)if __name__ __main__:#host#port#debugTrue:热加载方便调试app.run(debugTrue)5、额外数据
设置额外数据-make_response() 添加更多的响应信息 设置 cookie 设置响应头信息等 from flask import Flask
from flask import jsonify,render_template,make_responseappFlask(__name__)app.route(/)
def index():respmake_response(render_template(demo.html))#设置cookieresp.set_cookie(user,jimi)#设置响应头信息resp.headers[type]kobereturn respif __name__ __main__:#host#port#debugTrue:热加载方便调试app.run(debugTrue)六、测试平台环境配置
监听的主机 设置 host 参数 127.0.0.1 只能本机访问 0.0.0.0 服务发布到局域网 app.run(host0.0.0.0)监听的端口 设置 port 参数默认端口号 5000
app.run(host0.0.0.0, port5000)Debug 模式 设置 debugTrue默认是 production 实现热加载 开发调试方便 app.run(host0.0.0.0, port5000,debugTrue)七、接口配置
1、flask-restx 介绍
官方文档https://github.com/python-restx/flask-restx flask-restx 是一个支持 RESTFUL 的 flask 插件用于规范化接口的编写并且支持 swagger 文档。
2、插件安装
pip install flask-restx3、demo 示例
from flask import Flask
#from flask_restful import Resource,Api
from flask_restx import Resource,ApiappFlask(__name__)#1、创建api实例对象
apiApi(app)#2、使用api添加路由
api.route(/hello)
class HelloWorld(Resource): #3、类要继承Resource#4、定义restful风格的get方法def get(self):return {hello:world}# restful风格的post方法def post(self):return {post:success}if __name__ __main__:app.run(debugTrue)八、接口使用
1、设计框架的原则
复用性 高内聚低藕合
a、高耦合实例
问题判断条件过多业务逻辑非常复杂
app.route(/testcase,methods[GET,PUT,POST])
def select_case():### request:Requestif request.method GET:passelif request.method PUT:passb、低内聚示例
问题同一个路径对应多个请求方法代码没有复用
# get 请求
app.route(/testcase,methods[get])
def select_case():# request:Request# m request.methodprint(dir(request))return {code: 0, msg:get success}# post 请求
app.route(/testcase,methods[post])
def post_case():return {code: 0, msg:post success}# delete 请求
app.route(/testcase,methods[delete])
def delete_case():return {code: 0, msg:delete success}# put 请求
app.route(/testcase,methods[put])
def put_case():return {code: 0, msg:put success}2、编写 RESTFUL 风格的接口 导入from flask_restx import Resource,Api appFlask(name) 创建app实例对象 apiApi(app) 创建api实例对象 使用api添加路由 类要继承Resource 定义restful风格的方法 from flask import Flask
#from flask_restful import Resource,Api
from flask_restx import Resource,ApiappFlask(__name__)#1、创建api实例对象
apiApi(app)#2、使用api添加路由
#api.route(/user,/user1,/user2) 添加多个路由
api.route(/user)
class User(Resource): #3、类要继承Resource#4、定义restful风格的get方法def get(self,id):return {id:id,code:0,msg:get success}# restful风格的post方法def post(self):return {code:0,msg:post success}# restful风格的put方法def put(self):return {code:0,msg:put success}# restful风格的delete方法def delete(self):return {code:0,msg:delete success}api.add_resource(User,/user/int:id,/user_1)if __name__ __main__:app.run(debugTrue)3、添加路由的方式
方式一
添加多个路由 api.route(/user,/user1,/user2)
api.route(/user,/user1,/user2) 添加多个路由
api.route(/user)
class User(Resource):方式二
api.add_resource(User,/user/int:id,/user_1)
九、集成swagger
1、namespace 的使用
定义 Namespace 实例 为类添加装饰器 namespace.route(“”) 控制子路由 为命名空间指定访问资源路径 api.add_namespace(case_ns, ‘/case’)
from flask import Flask
from flask_restx import Api,Resource,NamespaceappFlask(__name__)
apiApi(app)#定义了2个命名空间
hello_nsNamespace(demo,descriptiondemo学习)
case_nsNamespace(case,description用例管理)#将api.route(case) 改为case_ns.route(/case)
#case_ns.route() 定义子路由如果没有的话传空字符串即可
case_ns.route()
class TestCase(Resource):def get(self):passdef post(self):passdef put(self):passdef delete(self):passhello_ns.route(/demo) #子路由
class Demo(Resource):def get(self):passdef post(self):passdef put(self):passdef delete(self):passapi.add_namespace(hello_ns,/hello)
api.add_namespace(case_ns,/case)if __name__ __main__:app.run(debugTrue)2、swagger 接口文档配置
定义参数 parser api.parser() 传递及校验参数 api.expect(parser) 或者 namespace.expect(parser)
a、api.parser()用法
格式api.parser().add_argument(参数名, 关键字参数) 第一个参数是参数名 后面是关键字传参常用的关键字有 type 类型 required 约束控制 choices 枚举参数 location 对应 request 对象中的属性
参数名参数值typeint,bool,float,string,FileStoragerequiredTrue/Falsechoices枚举locationargs,form,json,files
b、get 请求示例
from flask import Flask, request
from flask_restx import Resource, Api, Namespace,fields
from log_utils import logger
from werkzeug.datastructures import FileStorageapp Flask(__name__)
api Api(app)
hello_ns Namespace(demo, descriptiondemo学习)hello_ns.route()
class Demo(Resource):#定义parser解析器对象get_parser api.parser()#通过parser对象添加测试参数get_parser.add_argument(id,typeint,locationargs,requiredTrue)get_parser.add_argument(case_title,typestr,locationargs,requiredTrue)hello_ns.expect(get_parser)def get(self):logger.info(frequest.args {request.args})return {code: 0, msg: get success}api.add_namespace(hello_ns,/hello)if __name__ __main__:app.run(debugTrue)接口文档如下 c、post 请求示例
1、处理 json 格式
from flask import Flask, request
from flask_restx import Resource, Api, Namespace,fields
from log_utils import logger
from werkzeug.datastructures import FileStorageapp Flask(__name__)
api Api(app)
hello_ns Namespace(demo, descriptiondemo学习)hello_ns.route()
class Demo(Resource):post_parserapi.parser()post_parser.add_argument(id,typeint,locationjson,requiredTrue)post_parser.add_argument(casetitle,typestr,locationjson,requiredTrue)hello_ns.expect(post_parser)def post(self):logger.info(frequest.json {request.json})return {code: 0, msg: post success}api.add_namespace(hello_ns,/hello)if __name__ __main__:app.run(debugTrue)2、处理 files格式
from flask import Flask, request
from flask_restx import Resource, Api, Namespace,fields
from log_utils import logger
from werkzeug.datastructures import FileStorageapp Flask(__name__)
api Api(app)
hello_ns Namespace(demo, descriptiondemo学习)hello_ns.route()
class Demo(Resource):post_parserapi.parser()post_parser.add_argument(file,typeFileStorage,locationfiles,requiredTrue)hello_ns.expect(post_parser)def post(self):logger.info(frequest.files {request.files})return {code: 0, msg: post success}api.add_namespace(hello_ns,/hello)if __name__ __main__:app.run(debugTrue)请求接口
3、处理 form格式
from flask import Flask, request
from flask_restx import Resource, Api, Namespace,fields
from log_utils import logger
from werkzeug.datastructures import FileStorageapp Flask(__name__)
api Api(app)
hello_ns Namespace(demo, descriptiondemo学习)hello_ns.route()
class Demo(Resource):post_parserapi.parser()post_parser.add_argument(param1,helpusername,typeint,locationform,requiredTrue)post_parser.add_argument(param2,helppassword,typeint,locationform,requiredTrue)hello_ns.expect(post_parser)def post(self):logger.info(frequest.form {request.form})return {code: 0, msg: post success}api.add_namespace(hello_ns,/hello)if __name__ __main__:app.run(debugTrue)[2023-05-28 22:04:04] [INFO] [swagger_demo2.py]/[line: 53]/[post] request.form ImmutableMultiDict([(param1, 24), (param2, 123567)])
127.0.0.1 - - [28/May/2023 22:04:04] POST /hello HTTP/1.1 200 -4、处理choice格式
from flask import Flask, request
from flask_restx import Resource, Api, Namespace,fields
from log_utils import logger
from werkzeug.datastructures import FileStorageapp Flask(__name__)
api Api(app)
hello_ns Namespace(demo, descriptiondemo学习)hello_ns.route()
class Demo(Resource):post_parserapi.parser()post_parser.add_argument(choice, locationargs, requiredTrue,choices(1,2,3,4))hello_ns.expect(post_parser)def post(self):logger.info(frequest.args {request.args})return {code: 0, msg: post success}api.add_namespace(hello_ns,/hello)if __name__ __main__:app.run(debugTrue)[2023-05-28 22:06:14] [INFO] [swagger_demo2.py]/[line: 54]/[post] request.args ImmutableMultiDict([(choice, 2)])
127.0.0.1 - - [28/May/2023 22:06:14] POST /hello?choice2 HTTP/1.1 200 -十、orm介绍
1、什么是持久化
持久化Persistence 即把数据保存到可永久保存的存储设备中如磁盘。持久化的主要应用是将内存中的数据存储在关系型的数据库中。当然也可以存储在磁盘文件中、XML数据文件中等等。
2、什么是 ORM
Object Relational Mapping 对象关系映射 作用是在关系型数据库和对象之间做一个映射这样在具体操作数据库的时候就不需要再去和复杂的 SQL 语句打交道只要像平时操作对象一样操作就可以了
3、ORM 与 SQL 的对比
# 使用sql语句查询数据
sql SELECT
username, email, gender
FROM User WHERE id 1# 执行sql 代码
res db.execSql(sql);# 取出数据
name res[0]# 使用orm 查询数据定义ORM对象get 值
res db.session.query(\User.username, User.email, User.gender).\filter(User.id1).first()
name res.username4、ORM 优缺点
优势 隐藏了数据访问细节 ORM 使我们构造固化数据结构变得非常简单 缺点 性能下降 添加了关联操作性能不可避免的会下降一些 无法解决特别复杂的数据库操作 十一、orm中间件配置
from flask import Flask
# 实例化 Flask的类并且绑定module
from flask_sqlalchemy import SQLAlchemy
# 实例化 Flask
appFlask(__name__)
# mysql 数据库用户名
usernameroot
# mysql 数据库密码
pwdroot
# mysql 数据库的 host 地址
ip127.0.0.1
# mysql 数据库端口
port3306
# 代码使用的数据库名
datebasedemo
# 设置mysql 链接方法是
app.config[SQLALCHEMY_DATABASE_URL]fmysqlpymysql://{username}:{pwd}{ip}:{port}/{database}?charsetutf-8
# 定义应用使用数据库的配置
# 设置SQLALCHEMY_TRACK_MODIFICATIONS参数 不设置该配置的时候会抛出警告
app.config[SQLALCHEMY_TRACK_MODIFICATIONS]True
# 将 app 与 Flask-SQLAlchemy 的 db 进行绑定
dbSQLAlchemy(app)
十二、数据库与表管理
Flask-SQLAlchemy 数据库连接的配置 app.config[SQLALCHEMY_DATABASE_URI] mysqlpymysql://username:passwordhost:port/database database:username: rootpassword: rootserver: 127.0.0.1:3306db: flask_1定义数据库的表 需要继承 db.Modeldb 为 app 启动的时的 SQLAlchemy 绑定的实例 类名相当于表名 驼峰命名的类名转为下划线连接。例如 class UserInfo 建立的表名为 user_info 自定义表名__tablename__ 自定义的表名
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2023/5/28 22:37
# Author : 杜兰特
# File : sqlachemy_demo.pyfrom flask import Flask
from flask_sqlalchemy import SQLAlchemy
# 实例化app 对象
from sqlalchemy import *
import yamlapp Flask(__name__)
with open(./data.yaml) as f :result yaml.safe_load(f)username result.get(database).get(username)password result.get(database).get(password)server result.get(database).get(server)db result.get(database).get(db)
app.config[SQLALCHEMY_DATABASE_URI] \fmysqlpymysql://{username}:{password}{server}/{db}?charsetutf8
app.config[SQLALCHEMY_TRACK_MODIFICATIONS] True
# SQLAlchemy 绑定app
db SQLAlchemy(app)# 定义数据库的表 需要继承 db.Modeldb 为 app 启动的时的 SQLAlchemy 绑定的实例# 类名相当于表名
#驼峰命名的类名转为下划线连接。例如 class UserInfo 建立的表名为 user_info
#自定义表名__tablename__ 自定义的表名
class User(db.Model):__tablename__User #指定表名id Column(Integer, primary_keyTrue)username Column(String(80))class StudentInfo(db.Model):id Column(Integer, primary_keyTrue)username Column(String(80))if __name__ __main__ :#可以创建多个表db.create_all()#db.drop_all()创建表操作
可以创建多个表 db.create_all()
删除表操作
db.drop_all()
十三、对象与数据模型
1、数据模型
数据模型Data Model是数据特征的抽象它从抽象层次上描述了系统的静态特征、动态行为和约束条件为数据库系统的信息表示与操作提供一个抽象的框架。
2、设计用户表字段 3、Flask-SQLAlchemy 的属性字段定义
通常类的属性相当于表的一个字段 定义的属性的方式为 nameColumn(参数的类型, 其他的属性) 官方https://flask-sqlalchemy.palletsprojects.com/en/2.x/models/?highlightcolumn
参数类型含义Integer整型字段定义String(20)字符串字段定义括号为字符串的最大长度JSONjson 字符串字段DateTime时间格式字段
4、Flask-SQLAlchemy 字段常用关键字参数
参数类型含义primary_key是否主键autoincrement是否自增nullable是否允许为空unique是否允许重复default默认值
5、Flask-SQLAlchemy 对象与数据模型示例 每一个类变量表示一个数据库表的列名 第一个参数是表示数据的类型 primary_keyTrue 表示是主键 unique True 表示是不能重复的 nullableFalse 表示不可以为空 from sqlalchemy import *
from flask_sqlalchemy import SQLAlchemy
import yaml
# 导入 Query 以便于调用的时候代码提示
from sqlalchemy.orm import Query
from flask import Flask
app Flask(__name__)with open(./data.yaml) as f :result yaml.safe_load(f)username result.get(database).get(username)password result.get(database).get(password)server result.get(database).get(server)db result.get(database).get(db)
app.config[SQLALCHEMY_DATABASE_URI] \fmysqlpymysql://{username}:{password}{server}/{db}?charsetutf8
app.config[SQLALCHEMY_TRACK_MODIFICATIONS] True
# SQLAlchemy 绑定app
db SQLAlchemy(app)# 定义数据库的表 需要继承 db.Model
class User(db.Model):__tablename__ user # 设置数据库表名# 每一个类变量表示一个数据库表的列名# 第一个参数是表示数据的类型 primary_keyTrue 表示是主键id Column(Integer, primary_keyTrue)# unique True 表示是不能重复的 nullableFalse 表示不可以为空username Column(String(80), uniqueFalse, nullableFalse)email Column(String(120), uniqueTrue, nullableFalse)gender Column(String(3),uniqueFalse)def __repr__(self):# 数据库的 魔法方法 直观展示数据[User 张三,User 李四]return fUser {self.username}十四、数据CRUD
1、添加数据create
a、单条数据新增
实例化类创建表数据 将实例添加到 sessionadd 提交更新 (commit) 关闭 session
# 新增表数据需要导入 User 类进行实例化
userUser(id1,usernamekobe,email111qq.com,gender男)
print(user)
db.session.add(user)
db.session.commit()
db.session.close()b、多条数据新增
多次实例化类创建多条表数据 将多个实例依次添加到 session 中add或者一次性添加到 session 中add_all 提交更新 (commit) 关闭 session
# 批量添加数据操作
user1 User(usernamekobe1, email1113qq.com, gender男)
user2 User(usernamekobe2, email1114qq.com, gender女)
db.session.add_all([user1,user2])
db.session.commit()
db.session.close()2、读取数据read
a、查询表中全部数据
格式类.query.all()
# 读取全部数据
res User.query.all()
# 遍历数据得到想要的字段
for rs in res:print(rs.username, rs.email)b、条件查询——单条件查询
格式类.query.filter_by(条件).单条或多条
查询单条数据类.query.filter_by(条件).first()
resUser.query.filter_by(gender男).first()
print(res)查询多条数据类.query.filter_by(条件).all()
res_listUser.query.filter_by(gender男).all()
print(res_list)c、条件查询——多条件查询
查询单条数据类.query.filter_by(条件).filter_by(条件)…first()
res1User.query.filter_by(gender男).filter_by(usernamekobe1).first()
print(res1)查询多条数据类.query.filter_by(条件).filter_by(条件)…all()
res2 User.query.filter_by(gender男).filter_by(usernamekobe1).all()
print(res2)3、修改数据update
方式一 首先查询出来需要的数据 对查询出来的数据对象进行属性的修改 提交 session
user3User.query.filter_by(id2).first()
user3.gender女
db.session.commit()
db.session.close()方式二 给定查询条件进行查询后直接进行 update 操作 提交 session
res4User.query.filter_by(id3).update({username:butler})
db.session.commit()
db.session.close()4、删除数据delete
方式一 查询数据 对查询出来的数据对象进行删除操作 提交 session
user5User.query.filter_by(id1).first()
db.session.delete(user5)
db.session.commit()
db.session.close()方式二 给定查询条件进行查询后直接进行 delete 操作 提交 session
user5User.query.filter_by(id2).delete()
db.session.commit()
db.session.close()十五、多表关系-一对多
1、一对多关系
场景 一个班级有多个学生 一个学生只在一个班级 一对多关系中,通过外键来关联数据外键设置在多的一方
SQLAlchemy提供了一个relationship这个类可以定义属性以后在访问相关联的表的时候就直接可以通过属性访问的方式就可以访问得到了。另外可以通过backref来指定反向访问的属性名称。
特别注意 classinfodb.relationship(‘ClassInfo’,backref“studentinfo”)代表学生所属的班级信息backref:反向关联的属性名classinfodb.relationship(‘ClassInfo’,backref“studentinfo”)中的ClassInfo必须是另外一个相关联的类名
from sqlalchemy import *
from flask_sqlalchemy import SQLAlchemy
import yaml
# 导入 Query 以便于调用的时候代码提示
from sqlalchemy.orm import Query
from flask import Flask
app Flask(__name__)with open(../data.yaml) as f :result yaml.safe_load(f)username result.get(database).get(username)password result.get(database).get(password)server result.get(database).get(server)db result.get(database).get(db)
app.config[SQLALCHEMY_DATABASE_URI] \fmysqlpymysql://{username}:{password}{server}/{db}?charsetutf8
app.config[SQLALCHEMY_TRACK_MODIFICATIONS] True
# SQLAlchemy 绑定app
db SQLAlchemy(app)# 班级表
class ClassInfo(db.Model):__tablename__ Classid Column(Integer, primary_keyTrue)name Column(String(80))def __repr__(self):return fClass:{self.name}# 学生表
class StudentInfo(db.Model):# 指定表名__tablename__属性__tablename__ Studentid Column(Integer, primary_keyTrue)name Column(String(80))#添加外键classid Column(Integer, ForeignKey(Class.id))# 第一个参数表示这个关系的另一端是 ClassInfo 类。比如班级id1# 第二个参数backref, 表示反向引用需要从班级id为1 反向获取【多】的时候使用的属性# 通过ClassInfo实例.studentinfoclassinfodb.relationship(ClassInfo,backrefstudentinfo)def __repr__(self):return fStudent:{self.name}2、一对多表结构
创建表 db.create_all() 删除表 db.drop_all()
3、一对多增删查改
a、数据新增
Class 班级表添加两条数据
class1 ClassInfo(id1, name测开21期)
class2 ClassInfo(id2, name测开22期)
db.session.add_all([class1, class2])
db.session.commit()
db.session.close()要先完全创建好数据库中的班级表再去创建学生表 Student 学生表添加两条数据
student1 StudentInfo(id1, name学生一, classid1)
student2 StudentInfo(id2, name学生二, classid1)
student3 StudentInfo(id3, name学生三, classid2)
student4 StudentInfo(id4, name学生四, classid2)
db.session.add_all([student1, student2,student3, student4])
db.session.commit()
db.session.close()b、数据查询
多查一
通过学生id1 查询学生所在的班级
stu1StudentInfo.query.filter_by(id1).first()
#获取classid信息
print(stu1.classid)
print(stu1.classinfo)
print(stu1.classinfo.name)一查多
通过班级id1查询对应的学生
class1ClassInfo.query.filter_by(id1).first()
print(class1.studentinfo)
print(class1.studentinfo[0].name)c、数据修改
一改多
通过班级修改学生信息
class1ClassInfo.query.filter_by(id1).first()
print(class1.studentinfo)
class1.studentinfo[0].name学生修改1
db.session.commit()
db.session.close()多改一
通过学生修改班级信息
stu2StudentInfo.query.filter_by(id2).first()
print(stu2.classinfo)
stu2.classinfo.namepythonvip
db.session.commit()
db.session.close()d、数据删除
删除一个班级下的所有学生
class1ClassInfo.query.filter_by(id1).first()
StudentInfo.query.filter(StudentInfo.classidclass1.id).delete()
db.session.commit()
db.session.close()