如何在DRF序列化器中添加owner外键与transaction一对一字段创建实体
解决序列化器添加外键与一对一字段的问题
1. 处理owner外键字段(关联当前登录用户)
由于owner关联的是当前登录用户,不需要前端传递该字段,我们可以将其设为只读字段,在保存时直接从请求对象中获取登录用户赋值:
修改序列化器:
class CreateAppoinmentSerializer(serializers.ModelSerializer): class Meta: model = Appoinment fields = [ 'applicant_name', 'submission_date', 'appoinment_date', 'care_of', 'phone', 'appoinment_time', 'pass_seva_username', 'pass_seva_password', 'office', 'agency', 'paid', 'net_amount', # 补全未写完的字段名 'owner', 'transaction' # 新增两个字段 ] read_only_fields = ['owner'] # 标记owner为只读,无需前端传值
修改视图代码:
在调用save()方法时,直接传入owner参数,值为当前登录用户:
@permission_classes([IsAuthenticated]) @api_view(["POST"]) def createAppoinment(req): appoinment = CreateAppoinmentSerializer(data=req.data) if appoinment.is_valid(): # 传入当前登录用户作为owner字段的值 appoinment.save(owner=req.user) return Response(appoinment.data, status=status.HTTP_201_CREATED) # 注意:验证失败应返回400错误,而非404 return Response(appoinment.errors, status=status.HTTP_400_BAD_REQUEST)
2. 处理transaction一对一字段
分两种场景处理:
场景一:前端传递已存在的Transaction主键ID
如果前端会提供关联的Transaction的ID,在序列化器中显式定义该字段,指定查询集:
class CreateAppoinmentSerializer(serializers.ModelSerializer): # 显式定义transaction字段,允许前端传主键ID transaction = serializers.PrimaryKeyRelatedField(queryset=Transaction.objects.all()) class Meta: model = Appoinment fields = [ # 其他字段... 'owner', 'transaction' ] read_only_fields = ['owner']
此时前端只需在请求体中传入transaction: 1(对应Transaction的ID)即可完成关联。
场景二:后台自动创建Transaction并关联
如果需要在创建Appointment时自动生成关联的Transaction实例,可以重写序列化器的create方法,或者在视图中处理:
方式一:重写序列化器的create方法
class CreateAppoinmentSerializer(serializers.ModelSerializer): class Meta: model = Appoinment fields = [ # 其他字段... 'owner', 'transaction' ] read_only_fields = ['owner', 'transaction'] # transaction也设为只读 def create(self, validated_data): # 先创建Transaction实例(按需传入字段值) transaction = Transaction.objects.create() # 创建Appointment并关联transaction appointment = Appoinment.objects.create(transaction=transaction, **validated_data) return appointment
方式二:在视图中处理
@permission_classes([IsAuthenticated]) @api_view(["POST"]) def createAppoinment(req): appoinment = CreateAppoinmentSerializer(data=req.data) if appoinment.is_valid(): # 先创建Transaction实例 transaction = Transaction.objects.create() # 同时传入owner和transaction appoinment.save(owner=req.user, transaction=transaction) return Response(appoinment.data, status=status.HTTP_201_CREATED) return Response(appoinment.errors, status=status.HTTP_400_BAD_REQUEST)
注意事项
- 原视图中验证失败返回
HTTP_404_NOT_FOUND是错误的,应改为HTTP_400_BAD_REQUEST,因为404表示资源不存在,而请求数据无效属于客户端错误,对应400状态码。 - 确保
Appoinment模型中owner字段的定义正确,例如:owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name="appointments")。
内容的提问来源于stack exchange,提问作者Muhammed Rinshid
相关产品推荐
相关产品推荐

