Django REST API中serializer.save()设partner1为null致完整性错误
Django序列化器保存时partner1字段为null的问题分析及解决
问题场景
在Django项目中定义了business模型、对应序列化器及视图,GET请求功能正常,但执行POST创建数据时,明明验证后的validated_data包含partner1的有效值john,调用serialized_business.save()后该字段却被设为null,触发数据库非空约束错误。
1. 模型定义
class business(models.Model): business_category = models.ForeignKey(businessCategory, related_name='businesss', on_delete=models.CASCADE) partner1 = models.CharField(max_length=255) # 非空约束,未开启blank/null partner1_is_creator = models.BooleanField(default=True) partner2 = models.CharField(max_length=255) creator = models.ForeignKey(User, related_name='businesss', on_delete=models.CASCADE, null=True) name = models.CharField(max_length=255) setting = models.CharField(max_length=255) estimated_budget = models.FloatField() location = models.CharField(max_length=255) date_created = models.DateTimeField(auto_now_add=True) business_start_date = models.DateTimeField(null=True, editable=True, default=django.utils.timezone.now) business_end_date = models.DateTimeField(null=True, editable=True, default=django.utils.timezone.now)
2. 序列化器代码
class BusinessCreator(serializers.ModelSerializer): class Meta: model = business fields = ['business_category', 'name', 'partner1', 'partner2', 'partner1_is_creator', 'business_start_date', 'location', 'setting', 'estimated_budget']
3. 视图代码
class BusinessList(APIView): @method_decorator(login_required, name='dispatch') def get(self, request): created_user = request.user businesss = Business.objects.filter(creator=created_user) serializer = BusinessSummary(businesss, many=True) return Response(serializer.data) @method_decorator(login_required, name='dispatch') def post(self, request): new_business = request.data.get('business') serialized_business = BusinessCreator(data=new_business) if serialized_business.is_valid(raise_exception=True): print(serialized_business.validated_data) serialized_business.save() return Response(serialized_business.data, status=201) return Response(serialized_business.errors, status=400)
4. POST请求数据
{ "business":{ "business_category": 3, "name": "business1", "partner1": "john", "partner2": "smith", "partner1_is_owner": true, "business_start_date": "2024-09-18T08:03:00Z", "location": "CA", "setting": "club", "estimated_budget": 121.0 } }
5. 报错信息
IntegrityError at /business/businessviewall/
NOT NULL constraint failed: business_business.partner1
6. 验证后的数据输出
{'business_category': <BusinessCategory: food>, 'name': 'business1', 'partner1': 'john', 'partner2': 'smith', 'partner1_is_creator': True, 'business_start_date': datetime.datetime(2024, 9, 18, 8, 3, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'location': 'CA', 'setting': 'club', 'estimated_budget': 121.0}
问题原因
- 模型类名大小写不统一:
模型定义为小写的business,但视图GET方法中查询用了大写的Business,这会导致Django ORM的模型映射混淆——要么项目中存在另一个Business模型,要么ORM无法正确匹配序列化器绑定的模型,最终保存时字段映射错误,partner1未被正确写入。 - 请求字段名不匹配:
请求中传递的是partner1_is_owner,但模型和序列化器中字段为partner1_is_creator,虽然后者有默认值不影响验证,但属于数据传递的不规范问题。
解决方法
- 统一模型类命名规范:
按照Django约定,模型类使用大驼峰命名,修改模型类名并同步所有引用:# 模型修改 class Business(models.Model): # 字段定义保持不变 # 序列化器修改 class BusinessCreator(serializers.ModelSerializer): class Meta: model = Business # 同步改为大写 fields = ['business_category', 'name', 'partner1', 'partner2', 'partner1_is_creator', 'business_start_date', 'location', 'setting', 'estimated_budget'] - 修正请求字段名:
将POST请求中的partner1_is_owner改为partner1_is_creator,避免依赖默认值,确保数据传递准确。 - 同步数据库结构:
执行python manage.py makemigrations和python manage.py migrate,确保数据库表结构与当前模型一致,清理可能存在的重复表。
内容的提问来源于stack exchange,提问作者Nht_e0
相关产品推荐
相关产品推荐

