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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 14:00:51