06-蓝图实战(图书数据搜索与查询),编写get和post请求,同时应用WTForms参数验证
需求:之前的路由请求格式,不是通用的请求格式,转化为get 和 post请求之后,可以通过request方法获取其中的参数
参考格式 04-使用 Flask 框架实现 POST和GET接口 - 马铃薯1 - 博客园 (cnblogs.com)
@web.route('/book/search/<q>') def search(q): pass
第三方插件库,WTForms
在flask内部并没有提供全面的表单验证,所以当我们不借助第三方插件来处理时候代码会显得混乱,而官方推荐的一个表单验证插件就是wtforms。
wtfroms是一个支持多种web框架的form组件,主要用于对用户请求数据的进行验证,其的验证流程与django中的form表单验证由些许类似,本文主要介绍wtforms组件使用方法以及验证流程。
wtforms依照功能主要分为以下几个类别:
- Forms: 主要用于表单验证、字段定义、HTML生成,并把各种验证流程聚集在一起进行验证。
- Fields: 主要负责渲染(生成HTML)和数据转换。
- Validator:主要用于验证用户输入的数据的合法性。比如Length验证器可以用于验证输入数据的长度。
- Widgets:html插件,允许使用者在字段中通过该字典自定义html小部件。
- Meta:用于使用者自定义wtforms功能,例如csrf功能开启。
- Extensions:丰富的扩展库,可以与其他框架结合使用,例如django。
注意:
WTForms 表单类 searchForm
期待的输入是一个支持 getlist
方法的 MultiDict
类型
1) get请求获取的 request.args 是MultiDict
类型
2) post请求获取的 request.get_json() 是普通dict 类型,因此需要转换为 MultiDict(request.get_json()) 类型
pip安装
pip install wtforms
蓝图实战(图书数据搜索与查询)
项目结构
配置文件 config.py
# 配置参数 DEBUG = True
入口文件 fisher2.py
from flask import Flask, make_response, jsonify from datetime import datetime from app import create_app # 创建flask对象 app = create_app() if __name__ == '__main__': app.run(host= '0.0.0.0', debug=app.config['DEBUG'], port=5000)
视图函数,校验文件 app/form/book.py
# 使用WTForms验证用户输入参数的有效性 from wtforms import Form, StringField, validators class searchForm(Form): # 校验规则,参数不能为空、验证用户输入的字符串长度在1到30之间、 q = StringField(validators=[ validators.DataRequired(message="参数不能为空"), validators.Length(min=1, max=30)])
1) 创建蓝图
初始化 app/web/__init__.py
# 蓝图 blueprint 蓝本 from flask import Blueprint web = Blueprint('web', __name__) from app.web import book
指定路由和视图函数 app/web/book.py
from flask import jsonify, Blueprint, request from multidict import MultiDict from httpTest import HTTP from . import web from ..forms.book import searchForm # # 蓝图 blueprint 蓝本 # web = Blueprint('web', __name__) # 关键字搜索:http://t.talelin.com/v2/book/search?q={}&start={}&count={} # isbn搜索: http://t.talelin.com/v2/book/isbn/{isbn} ISBN_URL = "http://t.talelin.com/v2/book/isbn/{}" KEY_URL = "http://t.talelin.com/v2/book/search?q={}&start={}&count={}" # get请求 @web.route('/book/getSearch/', methods=['GET']) def getSearch(): print("========正在获取get请求=========") # # 从请求参数中获取 q # q = request.args.get('q') # print("参数q:", q) # 校验 form = searchForm(request.args) if form.validate(): # 从请求参数中获取 q (从form中取数,能够更好的验证) q = form.q.data # strip() 方法用于移除字符串头尾的空白字符或指定字符序列 q = q.strip() # 调用search_book_data方法,获取图书数据 result = search_book_data(q) return jsonify(result), 200 else: return jsonify(form.errors), 400 # post请求 @web.route('/book/postSearch/', methods=['POST']) def postSearch(): print("========正在获取post请求=========") # # 从请求参数中获取 q # # 首先获取 JSON 请求体 # data = request.get_json() # # 然后再从请求体中提取参数 # q = data.get('q') # print("参数q:", q) # 校验 # 首先获取 JSON 请求体 data = request.get_json() # 将 JSON 字典转换为 MultiDict form_data = MultiDict(data) form = searchForm(form_data) if form.validate(): # 从请求参数中获取 q (从form中取数,能够更好的验证) q = form.q.data # strip() 方法用于移除字符串头尾的空白字符或指定字符序列 q = q.strip() # 调用search_book_data方法,获取图书数据 result = search_book_data(q) return jsonify(result), 200 else: return jsonify(form.errors), 400 def search_book_data(q): # 调用is_isbn_or_key方法,判断q是关键字还是isbn isbn_or_key = is_isbn_or_key(q) # 根据isbn_or_key的值,获取相应的url if isbn_or_key == "isbn": url = ISBN_URL.format(q) print("进入isbn查询,url:", url) result = HTTP.get(url) else: url = KEY_URL.format(q, 1, 5) print("进入关键字查询,url:", url) result = HTTP.get(url) return result def is_isbn_or_key(q): # 默认q为关键字 isbn_or_key = "key" # 判断q是否为isbn # isbn13 是由13位0到9数字组成的字符串 # isbn10 是由10位0到9数字组成,含有一些 "-" if q.isdigit() and len(q) == 13: isbn_or_key = "isbn" short_q = q.replace("-", "") if q.isdigit() and len(short_q) == 10 and q in "-": isbn_or_key = "isbn" return isbn_or_key
视图函数文件 httpTest.py
import requests class HTTP: # 发送GET请求 @staticmethod def get(url, return_json=True): response = requests.get(url) if response.status_code == 200: if return_json: return response.json() else: return response.text else: print(f"Error: {response.status_code}") return None # 发送POST请求 @staticmethod def post(url, data, headers={}, return_json=True): response = requests.post(url, data=data, headers=headers) if response.status_code == 200: if return_json: return response.json() else: return response.text else: print(f"Error: {response.status_code}") return None
2) 注册蓝图,在初始化中实例化flask对象,并注册蓝图
初始化 app/__init__.py
from flask import Flask from app.web import web def create_app(): # 实例化flask对象 app = Flask(__name__) # flask对象加载配置文件 app.config.from_object('config') # 调用注册蓝图的方法 register_blueprint(app) return app def register_blueprint(app): # 注册蓝图 app.register_blueprint(web)
get请求测试
post请求测试
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix