使用 FastAPI 从下拉菜单中获取数据
Get data from a dropdown menu with FastAPI
在FastAPI项目中,可以方便的从HTML表单获取数据到后台。有内置的方法可以从文本输入、文件上传等获取数据。但是,下拉菜单似乎在我的项目中不起作用。 FastAPI 开发者 Tiangolo 有 addressed the issue after being requested and made a tutorial page including dropdown menus。我尝试按照与他相同的步骤操作,但我无法从下拉菜单中获取数据到我的后端。
我的代码如下所示:
view.py
:包含带有下拉值的枚举,并生成 html 模板。
class dropdownChoices(str, Enum):
water = "WATER"
fire = "FIRE"
electric = "ELECTRIC"
grass = "GRASS"
donut = "DONUT"
@router.get('/upload')
def upload(request: Request):
return templates.TemplateResponse('upload.html', context={'request': request, 'choices': [e.value for e in dropdownChoices]})
upload.html
: 将显示我的表单的模板,包含下拉菜单。
<form action="/upload" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="choices_dropdown">Choose:</label>
<select id="choices_dropdown" name="dropdown_choices">
{% for choice in choices %}
<option value={{choice}}>{{choice}}</option>
<!-- The choices are correctly displayed in the dropdown menu -->
{% endfor %}
</select>
</div>
<!-- More form actions including file upload and checkbox. These work. -->
<div class="form-group">
<label for="upload_file">Choose Upload File:</label>
<input type="file" class="form-control-file" name='upload_file' id="upload_file">
<input class="form-check-input" type="checkbox" name='overwrite_existing' id="flexCheckChecked"> Overwrite existing
</div>
<button id="upload" type='submit' class="btn btn-primary">Upload</button>
</form>
main.py
: 处理来自表单的数据。
# Gets data from upload.html
@app.post("/upload")
async def handle_form(request: Request,
choice: str = "WATER",
upload_file: UploadFile = File(...),
overwrite_existing: bool = Form(False)):
print(choice) #does NOT work: always print default ("WATER")
print(overwrite_existing) #Works, prints true or false depending on input
contents = await upload_file.file.read() #Works, file is later read etc
return templates.TemplateResponse('upload.html', context={'request': request,
'choices': [e.value for e in view.dropdownChoices]})
我觉得我已经完全按照教程进行了操作,但我总是得到默认选择。如果我不在我的 handle_form()
方法中添加默认选项,我将一无所获。
我不明白为什么用户在下拉菜单中的选择没有像其他的那样传输。
您在表格中的名字是 dropdown_choices
。您在 FastAPI 端点定义中的名称是 choice
。这些必须相同。您还想告诉 FastAPI 这也是一个表单字段(就像您对复选框所做的那样):
choice: str = Form("WATER"),
您还应该将选项值包装在 ""
:
<option value="{{choice}}">
select 箱子没有什么神奇之处;数据以通常的方式提交 - 通过 GET
或通过 POST
.
您总是获得默认选项,因为您设置了默认选项,并且发送时没有匹配的名称。
choice: str = "WATER",
在这里,你说你期望 choice
,不是作为枚举而是作为普通的 str
,并且你将默认值设置为文字 str "WATER"
。
但是在您的前端,您发送的名称为 dropdown_choices
.
<select id="choices_dropdown" name="dropdown_choices">
此外,通过这样的声明,Fastapi 会期望该值作为查询参数发送,但您的前端将其作为表单数据作为正文的一部分发送。
为了让 fastapi 正确地将它带到它所在的位置并正确验证它,您需要同时具有匹配的名称和类型。
async def handle_form(request: Request,
dropdown_choices: dropdownChoices = Form(dropdownChoices.water),
upload_file: UploadFile = File(...),
overwrite_existing: bool = Form(False)):
该值现在用正确的名称声明,应该作为枚举进行解析和验证directly.The默认值也被声明为枚举的成员,而不是不相关的 str。
在FastAPI项目中,可以方便的从HTML表单获取数据到后台。有内置的方法可以从文本输入、文件上传等获取数据。但是,下拉菜单似乎在我的项目中不起作用。 FastAPI 开发者 Tiangolo 有 addressed the issue after being requested and made a tutorial page including dropdown menus。我尝试按照与他相同的步骤操作,但我无法从下拉菜单中获取数据到我的后端。
我的代码如下所示:
view.py
:包含带有下拉值的枚举,并生成 html 模板。
class dropdownChoices(str, Enum):
water = "WATER"
fire = "FIRE"
electric = "ELECTRIC"
grass = "GRASS"
donut = "DONUT"
@router.get('/upload')
def upload(request: Request):
return templates.TemplateResponse('upload.html', context={'request': request, 'choices': [e.value for e in dropdownChoices]})
upload.html
: 将显示我的表单的模板,包含下拉菜单。
<form action="/upload" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="choices_dropdown">Choose:</label>
<select id="choices_dropdown" name="dropdown_choices">
{% for choice in choices %}
<option value={{choice}}>{{choice}}</option>
<!-- The choices are correctly displayed in the dropdown menu -->
{% endfor %}
</select>
</div>
<!-- More form actions including file upload and checkbox. These work. -->
<div class="form-group">
<label for="upload_file">Choose Upload File:</label>
<input type="file" class="form-control-file" name='upload_file' id="upload_file">
<input class="form-check-input" type="checkbox" name='overwrite_existing' id="flexCheckChecked"> Overwrite existing
</div>
<button id="upload" type='submit' class="btn btn-primary">Upload</button>
</form>
main.py
: 处理来自表单的数据。
# Gets data from upload.html
@app.post("/upload")
async def handle_form(request: Request,
choice: str = "WATER",
upload_file: UploadFile = File(...),
overwrite_existing: bool = Form(False)):
print(choice) #does NOT work: always print default ("WATER")
print(overwrite_existing) #Works, prints true or false depending on input
contents = await upload_file.file.read() #Works, file is later read etc
return templates.TemplateResponse('upload.html', context={'request': request,
'choices': [e.value for e in view.dropdownChoices]})
我觉得我已经完全按照教程进行了操作,但我总是得到默认选择。如果我不在我的 handle_form()
方法中添加默认选项,我将一无所获。
我不明白为什么用户在下拉菜单中的选择没有像其他的那样传输。
您在表格中的名字是 dropdown_choices
。您在 FastAPI 端点定义中的名称是 choice
。这些必须相同。您还想告诉 FastAPI 这也是一个表单字段(就像您对复选框所做的那样):
choice: str = Form("WATER"),
您还应该将选项值包装在 ""
:
<option value="{{choice}}">
select 箱子没有什么神奇之处;数据以通常的方式提交 - 通过 GET
或通过 POST
.
您总是获得默认选项,因为您设置了默认选项,并且发送时没有匹配的名称。
choice: str = "WATER",
在这里,你说你期望 choice
,不是作为枚举而是作为普通的 str
,并且你将默认值设置为文字 str "WATER"
。
但是在您的前端,您发送的名称为 dropdown_choices
.
<select id="choices_dropdown" name="dropdown_choices">
此外,通过这样的声明,Fastapi 会期望该值作为查询参数发送,但您的前端将其作为表单数据作为正文的一部分发送。 为了让 fastapi 正确地将它带到它所在的位置并正确验证它,您需要同时具有匹配的名称和类型。
async def handle_form(request: Request,
dropdown_choices: dropdownChoices = Form(dropdownChoices.water),
upload_file: UploadFile = File(...),
overwrite_existing: bool = Form(False)):
该值现在用正确的名称声明,应该作为枚举进行解析和验证directly.The默认值也被声明为枚举的成员,而不是不相关的 str。