You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF导入API JSON数据至数据库时遇字段非空错误排查

问题分析与解决方案

没错,这本质是数据结构解析错误,不是字段格式问题——你没有正确定位到外部API返回的实际题目数据节点,导致所有字段都提取到None,触发了序列化器的非空校验错误。

问题根源

看你打印的data输出和API返回结构:

{'response_code': 0, 'results': [{'category': 'General Knowledge', ...}]}

实际的题目数据是嵌套在results数组的第一个元素里的,但你的代码直接从顶层data对象提取字段(比如data.get('category')),而顶层对象根本没有这些键,所以所有字段都拿到了None,自然通不过models.py里定义的非空约束。

修复步骤

1. 修正数据提取路径

首先要从results数组中取出目标题目对象,再从中提取字段:

@api_view(['POST'])
def opendb(request):
    data = requests.get(url=request.data['url']).json()
    # 取出results数组里的第一个题目对象
    question_item = data['results'][0]
    QuestionData = {
        "category": question_item.get('category'),
        "type": question_item.get('type'),
        "difficulty": question_item.get('difficulty'),
        "question": question_item.get('question'),
        "answer": question_item.get('correct_answer'),
        "options": question_item.get('incorrect_answers'),
    }
    # 后续代码...

2. 处理关联模型的序列化问题

这一步很关键:你的Question模型里有多个关联字段(category是ForeignKey,options/answer是关联Options的关系),直接传字符串是无法通过ModelSerializer验证的,需要额外处理:

假设你的Category模型有一个name字段,Options模型有一个text字段,你需要:

  • 先获取或创建对应的Category实例
  • 创建所有选项(包括正确答案)的Options实例
  • 再关联到Question对象

修改后的完整视图代码示例:

@api_view(['POST'])
def opendb(request):
    data = requests.get(url=request.data['url']).json()
    question_item = data['results'][0]

    # 处理Category:获取或创建对应分类
    category, _ = Category.objects.get_or_create(name=question_item['category'])

    # 处理Options:创建所有选项(正确+错误)
    options = []
    # 添加错误选项
    for incorrect in question_item['incorrect_answers']:
        opt, _ = Options.objects.get_or_create(text=incorrect)
        options.append(opt)
    # 添加正确答案选项
    answer_opt, _ = Options.objects.get_or_create(text=question_item['correct_answer'])

    # 构建符合序列化要求的数据
    QuestionData = {
        "category": category.id,  # 传入关联对象的ID
        "type": question_item.get('type'),
        "difficulty": question_item.get('difficulty'),
        "question": question_item.get('question'),
        "answer": answer_opt.id,  # 传入正确选项的ID
        # ManyToMany字段通过主键列表传入
        "options": [opt.id for opt in options]
    }

    serializer = QuestionSerializer(data=QuestionData)
    if serializer.is_valid():
        serializer.save()
        return JsonResponse({"data": serializer.data}, status=status.HTTP_200_OK)
    return JsonResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

同时,确保你的QuestionSerializer正确配置了关联字段的序列化方式:

class QuestionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Question
        fields = ['id', 'category', 'question', 'options', 'answer', 'difficulty', 'type']
        # 对于ForeignKey和ManyToMany,默认用PrimaryKeyRelatedField,支持传入ID

验证修正效果

修改后,你提取的字段不再是None,同时关联字段也能正确匹配数据库中的实例,就能通过序列化器的校验,成功将数据存入Django数据库了。

内容的提问来源于stack exchange,提问作者Mohammed Adel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:33:12