21、flask-进阶-类视图和RESTful-前后端分离概念
前后端分离与不分离概念
-
前后端不分离:如 render_template('index.html', data=data) 这种就是前后端不分离前端和后端一起渲染
-
前后端分离:
- 后端返回json数据 - jsonify()
- 前端使用ajax来请求数据: ajax
- 各自处理各自的数据,代码不在一起
http请求方式:
- GET:查询
- POST:添加数据
- PUT:更新修改数据
- DELETE:删除数据
views.py
import requests from flask import Blueprint, jsonify from .models import * #创建蓝图(路由) blue = Blueprint('user', __name__) @blue.route('/') def index(): return 'index' # 前后端不分离:如 render_template('index.html', data=data) 这种就是前后端不分离前端和后端一起渲染 # 前后端分离: # 后端返回json数据 - jsonify() # 前端使用ajax来请求数据: ajax # jsonify(): 序列化 # http请求方式: # GET:查询 # POST:添加数据 # PUT:更新修改数据 # DELETE:删除数据 @blue.route('/users/', methods=['GET', 'POST', 'PUT', 'DELETE']) def users(): if requests.method == 'GET': return jsonify({'method', 'GET'}) elif requests.method == 'POST': return jsonify({'method', 'POST'}) elif requests.method == 'PUT': return jsonify({'method', 'PUT'}) elif requests.method == 'DELETE': return jsonify({'method', 'DELETE'})
RESTful - 后端接口编写
基本使用
- 安装
pip install flask-restful
- 修改项目目录结构
apis.py
from flask import jsonify from flask_restful import Resource # 类视图:CBV Class Based View # 函数视图:FBV Function Based View # 类视图 class HelloResource(Resource): # 继承Resource def get(self): # get请求,内部提供的 GET 方法 return jsonify({'msg': 'GET 请求'}) def post(self): # post请求,内部提供的 POST 方法 return jsonify({'msg': 'POST 请求'})
exts.py
from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate from flask_restful import Api #添加的 #初始化插件 db = SQLAlchemy() migrate = Migrate() api = Api() # 添加的 #和app对象绑定 def init_exts(app): db.init_app(app) migrate.init_app(app,db) api.init_app(app) # 添加的
urls.py
# 路由文件 from .exts import api from .apis import * # 路由 # api.add_resource(类名, '路由名') api.add_resource(HelloResource, '/hello/')
__init__.py
from flask import Flask from .exts import init_exts from .urls import * # 添加的 def create_app(): app = Flask(__name__) # 创建flask应用 #配置数据库 db_uri = 'sqlite:///sqlite3.db' #sqlite的配置 # db_uri = 'mysql+pymysql://root:123456@127.0.0.1:3306/flask_db?charset=utf8mb4' #mysql的配置 app.config['SQLALCHEMY_DATABASE_URI'] = db_uri app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False #初始化插件 init_exts(app=app) return app
项目结构如下:
字段格式化 - user_fields={}
- fields 进行定义
- marshal_with进行使用
特性:
1.显示我们设计的数据结构
2.默认返回的数据如果在预定义结构中不存在、数据会被自动过滤
3.如果返回的数据在预定义的结构中存在、数据会正常的返回
4.如果返回的数据比预定结构中的字段少,预定义的字段会呈现一个默认值
定义字段输出:
1.使用字典进行定义
2.常用都是基本类型:String, Integer
#格式化字段、返回的数据要遵循下面定义user_fields={}格式 user_fields = { 'msg': fields.String, 'status': fields.Integer, 'data': fields.String(attribute='private_data'), 'default_data': fields.String(default='1') } 3.定义好的格式通过装饰器进行使用
- @marshal_with(需要返回的数据格式), return返回字典就ok了
class Users(Resource): @marshal_with(user_fields) def get(self): return {'msg': '哈哈', 'data': '没有数据', 'age': '22', 'private_data': '表中数据'}
案例 - user_fields={}:
apis.py
from flask import jsonify from flask_restful import Resource, fields, marshal_with # Flask-RESTful # 1.字段格式化: 定义返回给前端的数据格式 ret_fields = { 'status': fields.Integer, # 状态码:规定返回的是整型 'msg': fields.String, # 状态信息:规定返回的是字符串类型 # 'data': fields.String # 数据:规定返回的是字符串类型 'like': fields.String(default='ball'), #如果返回的函数中没有包含这里定义的字段,则返回的数据中也会有这个字段,值为默认值 'like2': fields.String(), # 如果没有定义默认值,则返回的数据显示为None 'data2': fields.String(attribute='data') # attribute:关联函数中返回数据的某个字段名、并返回被关联字段的数据 } class UserResource(Resource): # 装饰器,将返回的数据格式化,严格要求返回的字典格式要符合ret_fields中定义的数据类型和字段的值 # 如果ret_fields={}中没有某个字段,则返回的数据中不会包含该字段、如没有`data`字段返回的数据就不会带`data`字段 @marshal_with(ret_fields) def get(self): return { 'status': 200, 'msg': 'OK', 'data': '给前端返回的数据 python' }
路由urls.py
# 路由文件 from .exts import api from .apis import * # 路由 # api.add_resource(类名, '路由名') api.add_resource(UserResource, '/user/')
案例2 - 获取数据库中的表数据
fields.Nested(user_fields) 级联模式,嵌套其它的
ret_fields
数据格式
这里嵌套了user_fields={}数据格式
apis.py
from flask import jsonify from flask_restful import Resource, fields, marshal_with from .models import * # 类视图:CBV Class Based View # 函数视图:FBV Function Based View # 返回数据库中的数据 # 给数据库中表的字段定义字段格式 # 这里我新建了一个用户表,字段有:id、name、age、sex user_fields = { 'id': fields.Integer, 'name': fields.String, 'age': fields.Integer, 'sex': fields.Boolean } # 定义请求返回的数据格式 ret_fields2 = { 'status': fields.Integer, 'msg': fields.String, #使用user对象 'data': fields.Nested(user_fields) } # 类视图 class User2Resource(Resource): @marshal_with(ret_fields2) # 装饰器,将返回的数据格式化 def get(self): user = User.query.first() # 查询数据库中的数据 return { 'status': 200, 'msg': 'OK', 'data': user }
路由urls.py
# 路由文件 from .exts import api from .apis import * # 路由 # api.add_resource(类名, '路由名') api.add_resource(User2Resource, '/user2/')
返回URL路径
连接字段
- 就是将当前的数据库的操作api暴露出来
- 根据提供的url和唯一标识进行数据操作
endpoint=标记的字段
absolute=True 返回绝对路径
'url': fields.Url(endpoint='id', absolute=True) #打上标记
返回列表数据
apis.py
from flask import jsonify from flask_restful import Resource, fields, marshal_with from .models import * # 类视图:CBV Class Based View # 函数视图:FBV Function Based View # --------------返回列表数据---------------------------- user_fields2 = { 'id': fields.Integer, 'name': fields.String, 'age': fields.Integer, 'sex': fields.Boolean, } # 定义请求返回的数据格式 ret_fields3 = { 'status': fields.Integer, 'msg': fields.String, #使用user对象 'data': fields.List(fields.Nested(user_fields2)) # List:列表 } # 类视图 class User3Resource(Resource): @marshal_with(ret_fields3) # 装饰器,将返回的数据格式化 def get(self): user = User.query.all() # 查询数据库中的所有数据 return { 'status': 200, 'msg': 'OK', 'data': user }
urls.py
# 路由文件 from .exts import api from .apis import * # 路由 # api.add_resource(类名, '路由名') api.add_resource(User3Resource, '/user3/')
前端参数解析
- 参数解析:解析前端发过来的数据
- 也是定义限制前端传过来的数据
- 导入:from flask_restful import reqparse
apis.py
from flask import jsonify from flask_restful import Resource, fields, marshal_with, reqparse from .models import * # 参数解析:解析前端发过来的数据 # 也是定义限制前端传过来的数据 # 导入:from flask_restful import reqparse parser = reqparse.RequestParser() # 创建解析对象 parser.add_argument('name', type=str, required=True, help='用户名不能为空') # 添加接收的参数, required=True:表示name一定要传过来 parser.add_argument('age', type=int, action='append') #action='append' 表示可以传多个age,所以传过来的是一个列表,可以为空 parser.add_argument('key', type=str, location='cookies') #获取cookie class User4Resource(Resource): def get(self): # 获取参数 args = parser.parse_args() name = args.get('name') age = args.get('age') key = args.get('key') return jsonify({'msg': 'OK', 'name': name, 'age': age, 'key': key})
urls.py
# 路由文件 from .exts import api from .apis import * # 路由 # api.add_resource(类名, '路由名') api.add_resource(User4Resource, '/user4/')
- 写一个爬虫去请求该路由并模仿前端传递参数
spider.py
import requests res = requests.get('http://127.0.0.1:5000/user4/', json={'name': 'lisi'}, headers={'Content-Type': 'application/json', 'Cookie': 'key=ABCDsdfaseadfasa'}) print(res.text)
本文作者:littlecc
本文链接:https://www.cnblogs.com/littlecc/p/18328231
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了