html - 我选择什么 enctype 将选项值保留为对象并保留支持类型 app/json?
问题描述
我正在尝试将选项的值作为 POST 表单中的对象发送,因此我使用 enctype='text/plain' 来获取对象而不是字符串。同时支持的媒体类型为 'application/json'
这里的模板:
<form class="" action="/api/meal_planner/" method="post" enctype='text/plain'>
{% csrf_token %}
<h3> Starters </h3>
{% for food in foods %}
{% if food.type == 'starter' %}
<div id="f{{ forloop.counter }}">
<h3> {{ food.display_name }} </h3>
<div class="details">
<ul>
<li>calories: {{food.cal}}</li>
<li>carbs: {{food.carbs}}</li>
<li>carbs: {{food.carbs}}</li>
<li>fibers: {{food.fibers}}</li>
<li>proteins: {{food.proteins}}</li>
<li>lipids: {{food.lipids}}</li>
</ul>
</div>
<div class="image">
<img src="{{food.imgUrl}}">
</div>
</div>
{% endif %}
{% endfor %}
<div class="select">
<select name='starter'>
{% for food in foods %}
{% if food.type == 'starter' %}
<option value='{"display_name":"{{food.display_name}}","cal":{{food.cal}}}'>{{ food.display_name }} </option>
{% endif %}
{% endfor %}
</select>
</div>
如您所见,选项是:
<option value='{"display_name":"{{food.display_name}}","cal":{{food.cal}}}'>{{ food.display_name }} </option>
所以我可以有这样的身体: POST的身体
这是 Django API:
@api_view(["POST"])
def FoodResponse(foodData):
try:
#defining variables
calMoy=500
percentage=0.1
calSum=0
donnee = json.loads(json.dumps(foodData.data))
print (donnee)
calSum= calSum + donnee["starter"]["cal"]+ donnee["dish"]["cal"]+ donnee["desert"]["cal"]
if ( (calSum < calMoy*(1-percentage)) or (calSum > calMoy*(1+percentage)) ):
return JsonResponse({
"status": "KO",
"food": donnee
})
else:
return JsonResponse({
"status": "OK",
"food": donnee
})
except ValueError as e:
return Response(e.args[0],status.HTTP_400_BAD_REQUEST)
这是错误:
解决方案
Django Rest Framework 默认允许application/json
或application/x-www-form-urlencoded
默认情况下的请求,除非您编写自己的text/plain
解析器(文档中有示例),text/plain
否则请求将被拒绝。
但是,我建议您不要尝试这样做。与其尝试使用纯文本编码将 JSON 作为表单中每个选择选项的值发送,不如使用每个Food
对象的主键,然后Food
使用主键在视图中查找对象会更明智。查找后,您可以检索卡路里和任何其他数据。
因此,在表单中,删除enctype="text/plain"
并修改构建下拉列表以使用Food
主键的方式:
<select name='starter'>
{% for food in foods %}
{% if food.type == 'starter' %}
<option value="{{ food.pk }}">{{ food.display_name }} </option>
{% endif %}
{% endfor %}
</select>
对菜和沙漠的其他下拉菜单执行相同的操作。
然后将视图修改为如下所示:
@api_view(["POST"])
def FoodResponse(request):
try:
#defining variables
calMoy=500
percentage=0.1
calSum=0
# Lookup the food objects up using the primary key
starter = Food.objects.get(pk=request.POST['starter'])
dish = Food.objects.get(pk=request.POST['dish'])
desert = Food.objects.get(pk=request.POST['desert'])
# Retrieve the calories and calculate the total
calSum= calSum + starter.cal+ dish.cal + desert.cal
...
推荐阅读
- python - ModuleNotFoundError:(已安装不工作)
- c++ - 与 pybind11 共享 Eigen::Matrix 的实例
- lightningchart - 仅缩放图表闪电js的x轴
- sql - 在将回车符和换行符视为普通空格时从 SQL 中选择
- cmake - 如果安装了新版本,为什么仍然使用旧版本的 cmake?
- c - 关于递归转置密码对任意长度字符串的推广
- javascript - 用户保存图像后 Safari 重新加载页面
- javascript - 使用 Cypress.io 对我自己的 Node 模块进行单元测试时出错
- python - Python Pandas:用三个不同的值在数据框中创建一列
- html - 避免画布元素上的分页符