Python DRF提交JSON对象时日期字段出现KeyError问题
咱们先来拆解一下你遇到的这个问题——用DRF创建继承AbstractUser的用户时,提交JSON触发日期字段的KeyError,大概率是字段映射、数据提交或者序列化器配置的问题,下面一步步来排查解决:
一、先核对序列化器字段和提交JSON的键名
这是最容易踩的坑!你得确保UserProfileSerializer里定义的日期字段名称,和你POST的JSON里的键完全一致,大小写、拼写都不能错。
举个例子,假设你的序列化器是这么写的:
from django.contrib.auth.models import AbstractUser from rest_framework import serializers class UserProfileSerializer(serializers.ModelSerializer): class Meta: model = AbstractUser # 或者你的自定义User模型 fields = ('username', 'email', 'birth_date') # 这里有个birth_date日期字段
那你提交的JSON必须用birth_date作为键,而不是birthday或者其他变体:
{ "username": "test_user", "email": "test@example.com", "birth_date": "1990-05-15" }
要是键名对不上,DRF找不到对应字段,直接就会抛出KeyError。
二、确认模型里确实有这个日期字段
如果你的序列化器里加了某个日期字段,但你的自定义User模型(继承AbstractUser)根本没定义这个字段,那肯定会出问题。
比如你要加birth_date,得先在模型里声明:
from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): # 必须先在模型里定义这个日期字段,序列化器才能用 birth_date = models.DateField(null=True, blank=True)
要是序列化器引用了模型不存在的字段,DRF解析数据时自然找不到对应的键,触发KeyError。
三、检查日期字段的必填性与提交数据
如果你的日期字段是必填项(模型里没设null=True或blank=True),但你提交的JSON里没传这个字段,也可能引发KeyError(或者伴随ValidationError出现)。这时候要么把模型字段改成可选,要么确保提交的JSON里必须包含该字段。
四、调试定位具体问题
要是上面的排查都没找到问题,咱们直接在视图里加调试代码,看看实际提交的数据和具体哪个键缺失:
from rest_framework import status from rest_framework.response import Response def post(self, request, format=None): # 先打印收到的所有数据,看看有没有你要的日期字段 print("提交的原始数据:", request.data) try: serializer = UserProfileSerializer(data=request.data) if serializer.is_valid(raise_exception=True): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) except KeyError as e: # 打印具体缺失的键,直接定位问题 print("缺失的字段:", str(e)) return Response({"error": f"缺少必填字段:{str(e)}"}, status=status.HTTP_400_BAD_REQUEST)
运行之后看控制台输出,就能精准知道是哪个字段出问题了。
五、检查序列化器的日期格式处理
如果你的日期字段有自定义格式,比如用了input_formats指定格式,那要确保提交的日期字符串符合要求。比如:
birth_date = serializers.DateField(input_formats=["%Y-%m-%d", "%d/%m/%Y"])
要是提交的日期格式不在这个列表里,DRF解析失败,也可能间接引发KeyError(不过更常见的是ValidationError,但也得排查一下)。
内容的提问来源于stack exchange,提问作者aLuViAn

