DRF可浏览界面未显示全部模型字段,无法添加支出对象求助
问题分析与解决方案
1. 「NOT NULL constraint failed: expenses_expense.created_by_id」错误原因及解决
这个错误是因为创建支出时,created_by字段未被赋值,但模型中该字段为必填项(NOT NULL)。你的AddExpense视图在perform_create方法里仅调用serializer.save(),没有传入当前登录用户作为created_by值。
解决方法:
修改AddExpense视图的perform_create方法,参考CategoryList的写法传入当前用户:
class AddExpense(generics.CreateAPIView): permission_classes = [permissions.IsAuthenticated] queryset = Expense.objects.all() serializer_class = ExpenseSerializer def perform_create(self, serializer): serializer.save(created_by=self.request.user) # 补充用户赋值
2. DRF界面不显示分类字段的原因及解决
你的ExpenseSerializer中把category字段定义为ReadOnlyField,该类型仅用于序列化输出(返回数据给前端),不支持反序列化输入(接收前端提交的数据),因此DRF可浏览界面不会显示该字段的输入控件。
解决方法:
修改ExpenseSerializer,将category替换为支持输入的字段类型,同时保留输出时显示分类名称的功能:
class ExpenseSerializer(serializers.ModelSerializer): created_by = serializers.ReadOnlyField(source='created_by.username') category_name = serializers.ReadOnlyField(source='category.name') # 新增:输出时显示分类名称 category = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all()) # 替换为可输入的主键选择字段 class Meta: model = Expense fields = ['created_by', 'amount', 'category', 'category_name', 'created_at', 'updated_at']
修改后,DRF界面会显示分类的下拉选择框(基于分类ID),提交时传入分类ID即可关联分类,输出数据时则会显示友好的分类名称。
3. 序列化器的问题总结
原序列化器存在两个核心问题:
category字段使用ReadOnlyField导致无法接收输入,无法关联分类created_by设为只读是合理的(无需用户输入),但视图未自动填充该字段值,触发数据库约束错误
修改后的序列化器既满足了输入需求(选择分类),又保留了友好的输出格式(显示分类名称),配合视图修改可彻底解决现有问题。
内容的提问来源于stack exchange,提问作者praxmon
相关产品推荐
相关产品推荐

