如何在FastAPI的Swagger UI中实现联动下拉菜单
问题背景
你现有一组问答数据,通过FastAPI+Pydantic搭建了提交接口,但在Swagger UI的表单中,选择下拉框的问题后无法自动关联填充对应答案,需要实现选问题自动填答案的动态联动效果。
现有代码
数据定义
quiz = [ {'question': 'Cassandra', 'response': '关系型', }, {'question': 'MongoDB et CouchDB', 'response': '面向对象', }, ] my_question = tuple(q['question'] for q in quiz)
FastAPI模型与接口
from pydantic import BaseModel, Literal from fastapi import FastAPI, Depends api = FastAPI() data = [] class Quiz(BaseModel): question: Literal[my_question] response: str @api.post("/postdata") def post_data(form_data: Quiz = Depends()): data.append(form_data) return data
解决方案
方案一:修改Swagger UI实现联动
通过给FastAPI的Swagger UI注入自定义JavaScript,监听下拉框变化并自动填充答案:
from fastapi import FastAPI, Depends from fastapi.openapi.docs import get_swagger_ui_html from pydantic import BaseModel, Literal quiz = [ {'question': 'Cassandra', 'response': '关系型', }, {'question': 'MongoDB et CouchDB', 'response': '面向对象', }, ] my_question = tuple(q['question'] for q in quiz) quiz_json = str(quiz).replace("'", '"') # 转成JS可识别的JSON格式 api = FastAPI(docs_url=None) # 关闭默认docs路由 data = [] class Quiz(BaseModel): question: Literal[my_question] response: str @api.post("/postdata") def post_data(form_data: Quiz = Depends()): data.append(form_data) return data # 自定义带联动逻辑的Swagger UI @api.get("/docs", include_in_schema=False) async def custom_swagger_ui_html(): return get_swagger_ui_html( openapi_url=api.openapi_url, title=api.title + " - Swagger UI", swagger_js_url="https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js", swagger_css_url="https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui.css", custom_js=f""" window.onload = function() {{ const quizData = {quiz_json}; // 监听表单渲染完成 const observer = new MutationObserver((mutations) => {{ mutations.forEach((mutation) => {{ if (mutation.addedNodes.length) {{ const questionSelect = document.querySelector('select[name="question"]'); if (questionSelect) {{ // 绑定下拉框变化事件 questionSelect.addEventListener('change', function() {{ const selected = this.value; const match = quizData.find(item => item.question === selected); if (match) {{ const responseInput = document.querySelector('input[name="response"]'); responseInput.value = match.response; }} }}); // 初始化填充默认问题的答案 const initialVal = questionSelect.value; if (initialVal) {{ const match = quizData.find(item => item.question === initialVal); const responseInput = document.querySelector('input[name="response"]'); responseInput.value = match.response; }} observer.disconnect(); }} }} }}); }}); observer.observe(document.body, {{ childList: true, subtree: true }}); }} """, )
方案二:自定义前端页面
如果不需要依赖Swagger UI,可直接写一个独立的HTML页面实现联动:
<!DOCTYPE html> <html> <head> <title>问答联动表单</title> </head> <body> <h3>选择问题提交</h3> <form id="quizForm"> <div> <label for="question">问题:</label> <select id="question" name="question"> <option value="Cassandra">Cassandra</option> <option value="MongoDB et CouchDB">MongoDB et CouchDB</option> </select> </div> <div> <label for="response">答案:</label> <input type="text" id="response" name="response" readonly> </div> <button type="submit">提交</button> </form> <script> const quizData = [ {'question': 'Cassandra', 'response': '关系型'}, {'question': 'MongoDB et CouchDB', 'response': '面向对象'} ]; const questionSel = document.getElementById('question'); const responseInput = document.getElementById('response'); // 初始化填充第一个问题的答案 responseInput.value = quizData[0].response; // 监听下拉框切换 questionSel.addEventListener('change', function() { const selected = this.value; const match = quizData.find(item => item.question === selected); responseInput.value = match.response; }); // 提交表单到FastAPI接口 document.getElementById('quizForm').addEventListener('submit', async function(e) { e.preventDefault(); const formData = Object.fromEntries(new FormData(this)); const res = await fetch('/postdata', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(formData) }); const result = await res.json(); alert('提交成功!返回数据:' + JSON.stringify(result)); }); </script> </body> </html>
将该HTML文件放入FastAPI的静态资源目录,通过配置StaticFiles即可访问使用。
内容的提问来源于stack exchange,提问作者aba2s
相关产品推荐
相关产品推荐

