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

如何让Django Rest Framework序列化器区分处理GET与POST请求

解决Bookmark API返回字段显示为字符串而非ID的问题

要实现GET请求返回user、collection、tags的字符串形式,同时不影响现有POST/PUT/PATCH的逻辑,可以通过为Serializer添加只读字段来实现,无需修改原有的create方法。

修改后的BookmarkSerializer代码

from rest_framework import serializers
from .models import Bookmark

class BookmarkSerializer(serializers.ModelSerializer):
    # 只读字段,用于返回字符串形式的数据
    user = serializers.StringRelatedField(read_only=True)
    collection = serializers.StringRelatedField(read_only=True, allow_null=True)
    tags = serializers.StringRelatedField(many=True, read_only=True)

    class Meta:
        model = Bookmark
        fields = "__all__"
    
    def create(self, validated_data):
        tags_data = validated_data.pop('tags', []) 
        bookmark = Bookmark.objects.create(**validated_data)

        for tag_data in tags_data:
              bookmark.tags.add(tag_data)
        
        return bookmark

代码说明

  1. StringRelatedField:这个字段会自动关联模型的__str__方法返回值,刚好匹配你需要的字符串格式:

    • user:依赖User模型的__str__方法(通常返回username,若你的User模型__str__不是username,可改用serializers.CharField(source='user.username', read_only=True))
    • collection:依赖Collection模型的__str__方法(需确保Collection模型的__str__返回名称,比如return self.name)
    • tags:因为是多对多关系,加上many=True,返回每个Tag的__str__值列表
  2. read_only=True:标记这些字段为只读,意味着序列化器在处理POST/PUT/PATCH请求时会忽略这些字段,完全不影响原有的创建、更新逻辑,依然使用传入的ID来关联数据。

  3. allow_null=True:针对collection字段(允许为null),避免当collection为None时序列化报错。

替代方案(自定义字段内容)

如果不想依赖模型的__str__方法,也可以用SerializerMethodField自定义返回内容:

class BookmarkSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField()
    collection = serializers.SerializerMethodField()
    tags = serializers.SerializerMethodField()

    class Meta:
        model = Bookmark
        fields = "__all__"
    
    def get_user(self, obj):
        return obj.user.username  # 直接指定返回用户名
    
    def get_collection(self, obj):
        return obj.collection.name if obj.collection else None  # 自定义返回集合名称
    
    def get_tags(self, obj):
        return [tag.name for tag in obj.tags.all()]  # 自定义返回标签名称列表
    
    def create(self, validated_data):
        # 保留原create方法不变
        tags_data = validated_data.pop('tags', []) 
        bookmark = Bookmark.objects.create(**validated_data)

        for tag_data in tags_data:
              bookmark.tags.add(tag_data)
        
        return bookmark

这种方式更灵活,能精准控制每个字段返回的内容,同样不会影响写操作逻辑。

内容的提问来源于stack exchange,提问作者Aditya Vaste

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 01:24:54