如何解决Django REST Framework中“Lists are not currently supported in HTML input”错误?
解决DRF嵌套序列化器HTML表单不支持列表的问题
问题原因
DRF默认的HTML表单渲染器无法处理many=True的嵌套序列化器字段,因此会抛出"Links: Lists are not currently supported in HTML input."的错误。以下是两种可行的解决方式:
方式一:使用JSON格式提交数据
这是最直接的解决方案,符合你提到的通过JSON处理嵌套序列化器的需求:
- 在DRF自带的API测试界面中,切换到Raw data标签页
- 将请求格式选择为
JSON,然后按照以下结构输入数据:{ "firstname": "你的名字", "lastname": "你的姓氏", "links": [ {"linkname": "GitHub", "linkurl": "https://github.com"}, {"linkname": "个人网站", "linkurl": "https://example.com"} ] } - 点击发送即可完成提交
如果是前端代码调用API,只需将请求的Content-Type设置为application/json,并将上述JSON作为请求体发送即可。
方式二:自定义HTML表单与视图处理(保留HTML提交)
如果需要通过传统HTML表单提交,可以通过动态添加字段+视图手动解析的方式实现:
1. 修改视图代码
from rest_framework.views import APIView from rest_framework.response import Response from .models import Work, Link from .serializers import WorkSerializer class WorkCreateAPIView(APIView): def post(self, request): # 创建Work主对象 work = Work.objects.create( firstname=request.data.get("firstname"), lastname=request.data.get("lastname") ) # 批量处理关联的Link数据 link_names = request.data.getlist("linkname[]") link_urls = request.data.getlist("linkurl[]") for name, url in zip(link_names, link_urls): if name.strip() and url.strip(): Link.objects.create( links=work, linkname=name, linkurl=url ) # 序列化并返回结果 serializer = WorkSerializer(work) return Response(serializer.data)
2. 前端HTML表单示例
<form method="post" action="/api/work/create/"> {% csrf_token %} <div> <label>Имя:</label> <input type="text" name="firstname" placeholder="Введите имя"> </div> <div> <label>Фамилия:</label> <input type="text" name="lastname" placeholder="Введите фамилию"> </div> <div id="links-container"> <div class="link-row"> <label>Название ссылки:</label> <input type="text" name="linkname[]" placeholder="Например: GitHub"> <label>URL:</label> <input type="text" name="linkurl[]" placeholder="Например: https://github.com"> </div> </div> <button type="button" onclick="addLinkRow()">Добавить еще ссылку</button> <button type="submit">Сохранить</button> </form> <script> function addLinkRow() { const container = document.getElementById("links-container"); const row = document.createElement("div"); row.className = "link-row"; row.innerHTML = ` <label>Название ссылки:</label> <input type="text" name="linkname[]" placeholder="Например: GitHub"> <label>URL:</label> <input type="text" name="linkurl[]" placeholder="Например: https://github.com"> `; container.appendChild(row); } </script>
额外优化建议
你的Link模型中外键字段命名为links容易造成混淆,建议修改为语义更清晰的work:
class Link(models.Model): work = models.ForeignKey(Work, related_name='links', on_delete=models.CASCADE, blank=True) linkname = models.CharField("linkname", max_length=100, blank=True) linkurl = models.CharField("linkurl", max_length=100, blank=True)
内容的提问来源于stack exchange,提问作者Елена М
相关产品推荐
相关产品推荐

