首页 > 解决方案 > 我选择什么 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)

这是错误:

错误不支持的媒体类型

标签: htmldjangodjango-rest-frameworkdjango-templates

解决方案


Django Rest Framework 默认允许application/jsonapplication/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

        ...

推荐阅读