DRF如何实现序列化器创建时接收ID、返回时输出序列化用户对象
DRF ModelSerializer 同字段写入传ID、返回用户对象的实现方案
方案1:拆分读写字段(DRF官方推荐写法)
核心思路:利用DRF字段的read_only、write_only属性,拆分两个字段分别处理读写逻辑,通过source参数映射到同一个模型字段。
首先定义返回用户基础信息的序列化器:
class UserBasicSerializer(serializers.ModelSerializer): class Meta: model = User # 替换为你项目的用户模型类 fields = ('id', 'username')
修改你的业务序列化器:
class InitiateDialogSerializer(ModelSerializer): initiator = ListUserViewSerializer(read_only=True) # 读字段:序列化返回时输出用户对象 answerer = UserBasicSerializer(read_only=True) # 写字段:仅接收用户ID,写入时映射到answerer字段 answerer_id = serializers.PrimaryKeyRelatedField( queryset=User.objects.all(), write_only=True, source='answerer' ) class Meta: model = Dialog fields = ('answerer', 'answerer_id', 'id', 'initiator') read_only_fields = ('id', 'initiator') def create(self, validated_data): validated_data['initiator'] = self.context['request'].user return super().create(validated_data)
使用说明:
- 创建数据时前端传入
answerer_id字段,值为数字类型的用户ID即可 - 接口返回结果仅包含
answerer字段,值为带id、username属性的用户对象,不会返回answerer_id字段
方案2:重写序列化方法(字段名统一)
如果你希望读写都用answerer作为字段名,不需要额外加_id后缀,可以重写to_representation方法修改序列化输出逻辑:
class InitiateDialogSerializer(ModelSerializer): initiator = ListUserViewSerializer(read_only=True) # 写入时接收用户ID,自动校验用户是否存在 answerer = serializers.PrimaryKeyRelatedField(queryset=User.objects.all()) class Meta: model = Dialog fields = ('answerer', 'id', 'initiator') read_only_fields = ('id', 'initiator') def create(self, validated_data): validated_data['initiator'] = self.context['request'].user return super().create(validated_data) # 重写输出逻辑,把answerer转为序列化后的用户对象 def to_representation(self, instance): data = super().to_representation(instance) data['answerer'] = UserBasicSerializer(instance.answerer).data return data
使用说明:
- 创建数据时前端直接传入
answerer字段,值为数字类型的用户ID即可 - 接口返回的
answerer字段自动转为带id、username的用户对象,前后端字段名完全统一
内容的提问来源于stack exchange,提问作者RomanGodMode
相关产品推荐
相关产品推荐

