Flask笔记十三:写一个简单的 JSON API Blueprint
上一篇我们把SECRET_KEY、数据库地址挪到了环境变量。网页端已经能看备忘录列表了但还会遇到这类需求手机脚本想 拉 JSON不想解析 HTML前端页面用 JavaScript 异步刷新 列表定时任务、小工具 HTTP 调一下 就能查数据这一篇做一件事在同一个项目里加第三个 Blueprintapi返回 JSON并且 复用第十篇的note_service不复制 SQL。例子仍是通用的Note备忘录不涉及任何真实业务。1. 学完后你能做什么新建apiBlueprintURL 统一带/api/前缀用jsonify返回 JSON正确设置 HTTP 状态码200 / 400 / 401 / 404列表接口 共用list_notes_for_user知道入门阶段 要不要做 Token 鉴权2. HTML 页面和 JSON 接口差在哪HTML 页面homeJSON 接口api返回render_template(...)jsonify({...})给谁用浏览器直接打开脚本、前端 JS、Postman错误提示flash 跳转{ok: false, msg: ...} 状态码查询逻辑note_service同一个note_service关键视图层换输出格式service 层不变。3. 目录长什么样在第十一、十二篇基础上加app/├── __init__.py├── home/├── admin/├── api/ # 新增│ ├── __init__.py│ └── views.py├── note_service.py├── auth_utils.py└── templates/三个 Blueprint 并列/notes/ → homeHTML 列表/admin/notes/ → adminHTML 后台列表/api/notes/ → apiJSON 列表4. 创建 api Blueprintapp/api/__init__.pyfrom flask import Blueprintapi Blueprint(api, __name__)import app.api.viewsapp/__init__.py里注册from app.api import api as api_blueprintapp.register_blueprint(api_blueprint, url_prefix/api)之后api.route(/notes/)的实际地址是/api/notes/。5. 第一个接口备忘录列表 JSONapp/api/views.pyfrom flask import jsonify, request, sessionfrom app.api import apifrom app.auth_utils import login_requiredfrom app.note_service import list_notes_for_userdef _note_to_dict(row):return {id: row.id,title: row.title,content: row.content or ,addtime: row.addtime.strftime(%Y-%m-%d %H:%M:%S) if row.addtime else ,}api.route(/notes/, methods[GET])login_requireddef notes_list():q (request.args.get(q) or ).strip()page request.args.get(page, 1, typeint)per_page request.args.get(per_page, 10, typeint)per_page min(max(per_page, 1), 50)page_data list_notes_for_user(session[user_id],qq,pagepage,per_pageper_page,)return jsonify({ok: True,items: [_note_to_dict(n) for n in page_data.items],page: page_data.page,pages: page_data.pages,total: page_data.total,has_next: page_data.has_next,has_prev: page_data.has_prev,})测试curl -b cookies.txt http://127.0.0.1:5000/api/notes/?q会议page1查询仍在note_serviceapi 视图只做读参数 → 调函数 → 转成 dict →jsonify。6. 单条查询与 404from app.note_service import get_note_for_userapi.route(/notes/int:note_id/, methods[GET])login_requireddef note_detail(note_id):row get_note_for_user(note_id, session[user_id])if not row:return jsonify({ok: False, msg: 记录不存在或无权访问}), 404return jsonify({ok: True, item: _note_to_dict(row)})JSON API 里 404 用状态码表达客户端靠状态码分支更简单。7. POST 新增一条JSON 请求体HTML 表单用request.formAPI 常用 JSON bodyfrom app import dbfrom app.models import Noteapi.route(/notes/, methods[POST])login_requireddef note_create():data request.get_json(silentTrue) or {}title (data.get(title) or ).strip()content (data.get(content) or ).strip()if not title:return jsonify({ok: False, msg: 标题不能为空}), 400note Note(titletitle,contentcontent,user_idsession[user_id],)db.session.add(note)db.session.commit()return jsonify({ok: True, item: _note_to_dict(note)}), 201状态码含义200成功GET201创建成功400参数错误401未登录404资源不存在8. 未登录时JSON 不要 redirectHTML 登录失败会redirect到登录页。API 客户端 跟不上 302应直接返回 JSONfrom functools import wrapsfrom flask import session, redirect, url_for, request, jsonifydef login_required(view):wraps(view)def wrapped(*args, **kwargs):if not session.get(user_id):if request.path.startswith(/api/):return jsonify({ok: False, msg: 请先登录}), 401return redirect(url_for(home.login, nextrequest.path))return view(*args, **kwargs)return wrapped同一装饰器 既能保护 HTML 页也能保护 API。9. 前端页面怎么调自己的 APIbutton typebutton idbtn-refresh-json用 API 刷新/buttonul idjson-note-list/ulscriptdocument.getElementById(btn-refresh-json).addEventListener(click, function () {fetch(/api/notes/?page1).then(function (res) {if (!res.ok) throw new Error(HTTP res.status);return res.json();}).then(function (data) {var ul document.getElementById(json-note-list);ul.innerHTML ;(data.items || []).forEach(function (n) {var li document.createElement(li);li.textContent n.title — n.addtime;ul.appendChild(li);});}).catch(function (err) {alert(加载失败 err.message);});});/script页面仍用 Jinja 渲染数据可以服务端渲染也可以 fetch API——查询规则都在note_service不会两套逻辑打架。10. 入门阶段要不要 Token 鉴权场景建议浏览器里 JS 调 同站/api/Session Cookie 够用手机 App、外部脚本需要 API Key 或 JWT后面专题完全公开的只读数据可不加登录但要限流入门阶段先 Session login_required把 JSON 格式和状态码写对。11. 统一 JSON 形状{ok: true, items: [...], page: 1}{ok: false, msg: 标题不能为空}成功ok: true 数据字段失败ok: falsemsg 合适的 HTTP 状态码12. 流程示意GET /api/notes/?q会议│▼login_required → 未登录401 JSON│▼list_notes_for_user(user_id, q会议, ...)│▼jsonify({ok: true, items: [...]})home.note_listHTML ──┐api.notes_listJSON ──┼── list_notes_for_userexport 脚本 ──┘13. 新手常踩的 6 个坑API 里render_template— 应只返回jsonify错误也返回 200 — 应return jsonify(...), 401忘记Content-Type: application/json— POST 用request.get_json()API 里复制 SQL — 都走note_service跨域一头雾水 — 同站调用不需要 CORSdatetime直接丢进 JSON — 先转成字符串14. 小结记住五件事第三个 Blueprintapi—url_prefix/apijsonify 状态码 — 错误用 4xx成功 200/201复用note_service— 不复制查询未登录返回 JSON 401 — 不要 redirect入门用 Session — Token 留给外部调用需求时十三篇连下来你已经会结构、数据库、WTForms CRUD、搜索、模板继承、Migrate、Flash、登录 Session、service 分层、admin Blueprint、环境变量、JSON API。

相关新闻

为什么选择StratoVirt?揭秘Rust虚拟技术如何革新云数据中心效率

为什么选择StratoVirt?揭秘Rust虚拟技术如何革新云数据中心效率

为什么选择StratoVirt?揭秘Rust虚拟技术如何革新云数据中心效率 【免费下载链接】stratovirt StratoVirt is an opensource VMM(Virtual Machine Manager) which aims to perform next generation virtualization.StratoVirt is based on Rust programming language…

2026/6/27 21:32:09阅读更多 →
登榜《财富》中国科技50强,创想三维用AI推动3D打印普及

登榜《财富》中国科技50强,创想三维用AI推动3D打印普及

导读:消费级3D打印行业正在进入新的竞争阶段。过去,行业比拼的重点更多集中在硬件参数与设备性能;如今,AI能力、生态体系、全球化渠道以及用户体验,正在成为企业能否打开大众市场的关键因素。6月25日,2026年…

2026/6/27 21:32:09阅读更多 →
计算机毕业设计之jsp基于SSM框架的智能车位管理系统的设计与实现

计算机毕业设计之jsp基于SSM框架的智能车位管理系统的设计与实现

近年来互联网络的迅猛发展和电子终端设备的普及,赋予了各行业充足的发展空间。智能车位管理系统相比于传统信息技术,时效性是它最大的特色,已经在电子娱乐、经济等中发挥着举足轻重的作用。2019年疫情的爆发,更是短时间内迅速扩大…

2026/6/27 21:32:09阅读更多 →
【中小学AI人工智能教育】多输出模型和不确定性加权技术

【中小学AI人工智能教育】多输出模型和不确定性加权技术

前面我们绍过使用AiEduLab.tech中“图像分类——手写数字识别”项目来完成图像分类模型的构建、训练、使用。实际上,AiEduLab.tech还支持多输出模型。有时我们不仅仅需要一组分类结果可能还希望同时得到另一组无法融合的结果。这可以通过训练另一个模型来实现&#…

2026/6/27 22:57:20阅读更多 →
怎么判断无人机装配线厂家的真实技术实力?5 步实测核验法

怎么判断无人机装配线厂家的真实技术实力?5 步实测核验法

最近好多做无人机制造的粉丝问我,怎么判断装配线厂家的真实技术实力?不少人被宣传册上的 “全自动化”“行业标杆” 话术忽悠,签完合同才发现是中间商转包,产线精度不达标、对接不了测试设备,返工损失动辄十几万。跑厂…

2026/6/27 22:57:20阅读更多 →
Windows配置DNS解析临时域名

Windows配置DNS解析临时域名

Windows Server 自带 DNS 服务(推荐,局域网统一域名,所有人不用改 hosts) 搭建内网 DNS,全局域网电脑 DNS 填192.168.1.66,直接访问 http://hub.local:5005,所有网段自动解析,一台服…

2026/6/27 22:57:20阅读更多 →
零碳园区管理系统的价值如在实际项目中体现

零碳园区管理系统的价值如在实际项目中体现

当前国内零碳园区建设已从概念试点、硬件堆砌阶段,全面迈入数字化落地、可量化收益、长效化运营的实战阶段。传统园区改造普遍存在新能源设备利用率低、用电成本居高不下、能耗管控粗放、碳效合规缺失、运维成本高昂、供电稳定性不足等实操痛点。零碳园区智能化管理…

2026/6/27 22:57:20阅读更多 →
量子力学核心:定义、公理与关键概念

量子力学核心:定义、公理与关键概念

在极小尺度下,宇宙的运行规律与我们日常所见的世界截然不同。量子力学作为物理学的一个重要分支,专门用来描述原子、电子、光子,以及分子、亚分子尺度下几乎所有物质的奇异特性。 量子力学诞生于20世纪上半叶,它推导得出的结论往往…

2026/6/27 22:57:20阅读更多 →
龙客文化GEO运营用了三个月,真的有效果吗?

龙客文化GEO运营用了三个月,真的有效果吗?

说实话,刚开始接触龙客文化GEO的时候,我心里也是打鼓的。我们做的是本地生活服务的,之前试过投竞价、搞地推,钱花了不少,但效果就跟打水漂一样,看得见摸不着。最头疼的就是客户搜不到我们,明明服…

2026/6/27 22:52:20阅读更多 →
【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体 一文搞定到底什么是智能体【人工智能】一文搞定到底什么是智能体一. LM,WorkFlow,Agent分别有什么么不同二. Agent的思考过程是怎样的三. Agent的五个核心部分1)LLM2)Prompt3)Me…

2026/6/27 11:20:40阅读更多 →
嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

1. 嵌入式GUI控件:从原理到实战的深度解析在嵌入式系统开发中,图形用户界面(GUI)的设计与实现往往是项目从“能用”到“好用”的关键一跃。不同于资源充沛的PC或移动平台,嵌入式设备的GUI需要在有限的CPU性能、内存空间…

2026/6/27 5:46:02阅读更多 →
Google AI Studio 300美元额度的真相与实战指南

Google AI Studio 300美元额度的真相与实战指南

1. 这300美金不是“送钱”,而是Google埋下的第一道技术门槛 你看到标题里那个醒目的“$300美金”时,第一反应可能是:又一个免费额度?领完就完事?我亲手试过——这300美金根本不是红包,而是一张入场券&…

2026/6/27 11:20:39阅读更多 →
10分钟AI语音克隆与实时变声:Retrieval-based-Voice-Conversion-WebUI完整指南

10分钟AI语音克隆与实时变声:Retrieval-based-Voice-Conversion-WebUI完整指南

10分钟AI语音克隆与实时变声&#xff1a;Retrieval-based-Voice-Conversion-WebUI完整指南 【免费下载链接】Retrieval-based-Voice-Conversion-WebUI Easily train a good VC model with voice data < 10 mins! 项目地址: https://gitcode.com/GitHub_Trending/re/Retrie…

2026/6/27 0:04:03阅读更多 →
Layerdivider:3分钟AI智能分层,彻底告别手动抠图时代

Layerdivider:3分钟AI智能分层,彻底告别手动抠图时代

Layerdivider&#xff1a;3分钟AI智能分层&#xff0c;彻底告别手动抠图时代 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider 还在为复杂的图像分层工作烦…

2026/6/27 0:04:03阅读更多 →
Tomcat中X-Frame-Options配置实战:防御点击劫持的四种方法与最佳实践

Tomcat中X-Frame-Options配置实战:防御点击劫持的四种方法与最佳实践

1. 项目概述&#xff1a;为什么X-Frame-Options是Web安全的“防盗门”&#xff1f;最近在排查一个老项目的安全审计报告时&#xff0c;又被提到了“点击劫持”风险&#xff0c;矛头直指缺失的X-Frame-Options响应头。这已经不是第一次了&#xff0c;很多开发团队&#xff0c;尤…

2026/6/27 0:04:03阅读更多 →