当前位置: 首页 > news >正文

flask实现后端接口的封装和开发部分

flask:实现后端接口的封装和开发部分

HTTP 请求方法和响应

对照后面的代码案例,我们看看 Flask-Restful 是如何去发起请求并处理响应的。

from flask import Flask, request
from flask_restful import Api, Resourceapp = Flask(__name__)
api = Api(app)class HelloWord_Flask(Resource):def get(self):return {"message": "Hello World!"}def post(self):# 处理POST请求data = request.get_json()  # 获取JSON数据return {"received": data}, 201  # 返回接收到的数据和状态码
api.add_resource(HelloWord_Flask, '/')if __name__ == '__main__':app.run(debug=True)

​ 我们创建了一个 Flask 应用和一个 RESTful API 实例,定义了一个 HelloFlask 类作为资源,处理 GET 和 POST 请求,并且在根路径 (“/”) 上添加了这个资源。

​ POST 方法与 GET 方法不同,不能直接在浏览器输入 URL 来测试执行结果。我们可以借助工具 requests 来测试,它是 Python 的一个 HTTP 库(Python 的第三方库),可以通过 pip 来安装使用,它允许我们发送 HTTP 请求并获取响应。

你可能需要:RequestParser 对象-----自动验证和解析HTTP请求中的参数

常用参数选项

参数 描述 示例
type 参数类型 str, int, float, bool
required 是否必需 required=True
help 错误提示信息 help='参数不能为空'
default 默认值 default='guest'
choices 可选值列表 choices=['male', 'female']
location 参数位置 location='args' (查询参数)

如果我们flask这样

class HelloWord_Flask_two(Resource):# 创建一个RequestParser对象,用于解析请求参数,设置规则parser = reqparse.RequestParser()parser.add_argument('name', type=str, required=True, help='name参数不能为空')parser.add_argument('location', type=str, required=True, help='location参数不能为空')parser.add_argument('age', type=int, required=True, help='age参数不能为空')def get(self):return {"message": "Hello World!"}def post(self):# 处理post请求args = self.parser.parse_args()  # 解析请求参数# 验证参数name = args['name']location = args['location']age = args['age']return {"name": name, "location": location, "age": age}, 201
api.add_resource(HelloWord_Flask_two, '/')      

注:name = args[‘name’] 和 age = args[‘age’] 作用是获取请求参数中的 ‘name’ 值和 ‘age’ 值

验证:

import requests
#发送一个get请求
response = requests.get('http://localhost:5000/')
print(response.json())
#发送一个post请求
data = {"name": "Alice", "age": 30}
response = requests.post('http://localhost:5000/', json=data)
print("没有传location参数时的响应:")
print(response.json())
data2 = {"name": "Alice", "location": "Wonderland", "age": 30}
response = requests.post('http://localhost:5000/', json=data2)
print("传入所有参数时的响应:")
print(response.json())

令人更加兴奋的是:可以结合蓝图使用

文件目录

代码部分

这是api/models/user.py下的具体实现代码

from werkzeug.security import generate_password_hash, check_password_hash
class UserLogin(BaseModels,db.Model):
# 其中 BaseModels 是一个基础模型类,db.Model 是一个数据库模型类。模型里面包含的字段就是登录功能相关的字段信息。"""用户登录模型"""__tablename__ = 'user_login'  # 指定表名为 user_loginid = db.Column(db.Integer, primary_key=True, autoincrement=True)  # 主键,自增mobile = db.Column(db.String(16),unique=True,nullable=False)  # 手机号,唯一且不能为空password_hash = db.Column(db.String(128),nullable=False)  # 密码哈希值,不能为空user_id = db.Column(db.Integer,nullable=False)  # 用户ID,不能为空last_login = db.Column(db.DateTime, default= datetime.now)  # 最后登录时间last_login_stamp = db.Column(db.Integer) #最后登录时间戳@property# 将一个属性方法封装成属性def password(self):raise AttributeError('密码不可读(密码属性不可直接获取)')@password.setter# 定义password的setter方法def password(self, value):self.password_hash = generate_password_hash(value)# 传入的是明文,效验明文和数据库里的hash之后密码,正确为truedef check_password(self, password):return check_password_hash(self.password_hash, password)

你现在应该知道UserLogin 模型基类主要实现的功能。现在我们要把请求响应处理好,这样在接口请求之后,才能更好地贴合业务逻辑。建议你把 response_utils.py 存放在 api/utils/response_utils.py 这个文件路径上。

from flask import jsonify
class HttpCode(object):ok = 200               # 成功params_error = 400     # 参数错误server_error = 500     # 服务器错误auth_error = 401       # 认证错误method_error = 405     # 方法不允许db_error = 1001        # 自定义数据库错误
def rep_result(code,msg,data):#{"code"= 200,"msg" = 'baababaab',"data"={}}return jsonify({'code': code,'msg': msg,'data': data or {}  # data为空时,返回{},就是确保data不为空})
def success(msg,data = None):return rep_result(code = HttpCode.ok,msg = msg,data = data)
def error(code,msg,data = None):return rep_result(code = code,msg = msg,data = data)

响应格式标准化:这个工具类确保所有API响应都遵循统一的JSON格式:

{"code": 200,"msg": "操作成功","data": {"user_id": 1,"username": "john"}
}

错误的响应为:

{"code": 400,"msg": "参数错误:用户名不能为空","data": {}
}

成功响应与错误响应的统一格式以及对应的 success() 和 error() 方法。rep_result 方法用来返回响应结果,该方法接受三个参数:code(状态码)、msg(提示信息)和 data(响应数据),并通过 jsonify 函数将结果转换成 JSON 格式并返回。

在后端开发中需要返回处理结果的时候,直接调用 success() 或 error() 方法即可。

我们需要创建一个 login.py 文件,文件存放路径我写在下面的api/modules/auth/login

from flask import current_app
from flask_restful import Resource, reqparse,inputs
from api.models.user import UserLogin
from api.utils.auth_helper import Auth
from api.utils.response_utils import error,HttpCode#Login 类继承自 Resource,表示这是一个RESTful资源
class Login(Resource):'''用户登录接口'''def post(self):# 创建解析对象parser = reqparse.RequestParser(bundle_errors=True)# 添加参数parser.add_argument('mobile',type = inputs.regex('1[3456789]\\d{9}'),nullable = False,location = ['form']  ,required = True,help = '请输入正确的手机号')parser.add_argument('password',type = str,required = True,nullable = False,location = ['form'],help = '密码参数不正确')# location=['form'] 表示从 HTTP请求的表单数据(Form Data) 中获取参数值。# 解析参数args = parser.parse_args()# 通过手机号取出用户对象try:user_login = UserLogin.query.filter(UserLogin.mobile == args.mobile).first()except Exception as e:current_app.logger.error(e)return error(code = HttpCode.db_error,msg = '数据库查询异常(查询手机号异常)')# 验证拿到这个手机号,是否在我们的登录信息中存在  异常捕获# 判断我们的用户信息不在时,返回错误信息的响应码if not user_login:return error(code=HttpCode.db_error,msg='用户不存在')return Auth().authenticate(args.mobile,args.password)

​ 定义 LoginView 类作为资源,用于处理 POST 请求。在创建 RequestParser 对象时,参数 bundle_errors=True 能将请求参数校验时发生的所有错误,都打包成一个列表返回。随后我们向参数解析器 parser 中添加 mobile 和 password 参数。这些参数的含义你可以参考后面的表格。

​ 完成视图函数之后,我们再看看蓝图层具体该如何实现。在蓝图层,注册名为 auth_blu 的蓝图,它的 URL 前缀是 /auth。这意味着,对于使用这个蓝图的路由,都需要以 /auth 开头。通过 add_resource 方法将 LoginView 视图和路径 ‘/login’ 绑定, LoginView 的完整 URL 变成了 ‘/auth/login’。

from flask import Blueprint
from flask_RESTful import Api
from api.modules.auth.login import LoginView
auth_blu = Blueprint('auth', __name__, url_prefix='/auth')
api = Api(auth_blu)
api.add_resource(LoginView, '/login')

在 api 的 init.py 文件中,添加对应的蓝图初始化

from api.modules.auth import auth_blu
app.register_blueprint(auth_blu)
api/modules/auth/
├── __init__.py
└── login.py         # LoginView 类应该直接在这里

其他注意知识点:

@property 方法 - 像属性一样访问

class User:def __init__(self, name):self._name = name# 普通方法 - 需要加括号调用def get_name(self):return self._name# @property 方法 - 像属性一样访问@propertydef name(self):return self._name# 使用区别
user = User("Alice")# 普通方法调用
print(user.get_name())  # 需要括号 → "Alice"# @property 方法调用
print(user.name)        # 不需要括号 → "Alice"

@property
def password(self):raise AttributeError('密码不可读')@password.setter  # 👈 注意这里!
def password(self, value):self.password_hash = generate_password_hash(value)#当执行 user.password = "明文密码" 时
#会自动调用 @password.setter 装饰的方法
#将明文密码哈希后存储到 password_hash 属性中
class User:def __init__(self):self.password_hash = None@propertydef password(self):"""读取时:抛出错误"""raise AttributeError('密码不可读')@password.setter  # 👈 设置器def password(self, value):"""赋值时:自动哈希密码"""self.password_hash = generate_password_hash(value)def check_password(self, plain_password):"""验证密码"""return check_password_hash(self.password_hash, plain_password)# 使用示例
user = User()# 赋值操作 → 触发 @password.setter
user.password = "my_password_123"  
# 等价于:user.password("my_password_123") 但语法更优雅# 读取操作 → 触发 @property
# user.password  # 会报错:AttributeError# 验证密码
result = user.check_password("my_password_123")  # True
操作类型 装饰器 用途 示例
读取 @property 定义获取属性时的行为 print(user.password)
赋值 @属性名.setter 定义设置属性时的行为 user.password = "123"
删除 @属性名.deleter 定义删除属性时的行为 del user.password

bundle_errors=True

bundle_errors=True 表示将所有参数验证错误打包在一起返回,而不是在遇到第一个错误时就停止验证。

对比演示

bundle_errors=False

parser = reqparse.RequestParser(bundle_errors=False)  # 默认值parser.add_argument('mobile', required=True, help='手机号必填')
parser.add_argument('password', required=True, help='密码必填')
parser.add_argument('email', type=inputs.email, help='邮箱格式错误')# 如果mobile和password都为空,只会返回第一个错误
args = parser.parse_args()

响应结果

{"message": {"mobile": "手机号必填"}
}
// 只显示第一个错误,不知道password也有问题

bundle_errors=True

parser = reqparse.RequestParser(bundle_errors=True)  # 启用错误打包parser.add_argument('mobile', required=True, help='手机号必填')
parser.add_argument('password', required=True, help='密码必填')
parser.add_argument('email', type=inputs.email, help='邮箱格式错误')# 即使有多个错误,也会一起返回
args = parser.parse_args()

响应结果

{"message": {"mobile": "手机号必填","password": "密码必填"}
}
// 同时显示所有错误字段
http://www.hskmm.com/?act=detail&tid=14288

相关文章:

  • 上海这样的地段简直是逆天
  • 【GitHub每日速递 250923】 Google 又放大招!TimesFM 2.5 参数减半,预测更准更快
  • 具身智能机器人架构:人形机器人系统架构深度拆解
  • 卓驭,欧洲无绝境
  • 下周审核4家IPO,2家再融资。其中两家IPO企业于在审期间调减募资规模
  • 280亿国产AI独角兽,惹怒“地表最强法务部”
  • 读人形机器人20财富再分配
  • Java 与人工智能的深度融合:从数据到推理服务
  • Java 与大数据实时处理:Kafka、Flink 与企业应用
  • Java 与企业级中间件:消息、缓存与数据库集成
  • 基于 Vite7 与 Vue3 的 WebOS 后台系统架构实践
  • 啊哈哈20250923_03:23
  • js获取浏览器指纹
  • gitIgnore 无法忽略dist目录的变更
  • 翻转二叉树
  • 我的第一篇博客
  • 测试测试测试测试测试
  • java中的浮点数计算
  • XYCTF2025复现(WEB)
  • 洛谷 P13973 [VKOSHP 2024] Nightmare Sum
  • 发布/订阅(Publish/Subscribe)与交换机(Exchange)
  • 线性结构之链表
  • 二叉树最近公共祖先
  • AI 编程“效率幻觉”:为何你感觉快了,项目却慢了?
  • lc1033-移动石子直到连续
  • 一些正在制作的“格林达姆”测试项目,以及“假无损”
  • 个人项目
  • 北京 意大利学签 北京意大利签证中心 贵宾 vip vfs
  • 第1周
  • 多商家在线客服系统 - 客服用户表设计方案