V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
firejoke
V2EX  ›  Django

关于如何根据 Accept 的 media_type 返回不同类型序列化数据的想法

  •  
  •   firejoke · 2021-11-19 18:04:57 +08:00 · 1721 次点击
    这是一个创建于 1085 天前的主题,其中的信息可能已经有所发展或是发生改变。

    DRF 的 HyperLinkedRelatedField 非常好用,但请求 Json 格式的数据的时候,还要在根据返回的 url 字段再请求一遍,所以有了个想根据请求头确定返回数据类型的想法

    class BaseSerializer(serializers.HyperlinkedModelSerializer):
    
        def __new__(cls, *args, **kwargs):
            media_field = kwargs["context"]["request"].accepted_media_type
            if hasattr(cls, "related_fields"):
                for name, fields in cls.related_fields.items():
                    if "text" in media_field:
                        field = fields.get("text", None)
                    elif "json" in media_field:
                        field = fields.get("json", None)
                    elif "yaml" in media_field:
                        field = fields.get("yaml", None)
                    else:
                        log.error(f"{name} not found any type field")
                        continue
                    cls._declared_fields[name] = field
                    cls.Meta.fields += (name,)
            return super().__new__(cls, *args, **kwargs)
    

    根据请求头里包含的 accepted_media_type 来判断
    使用方法

    class PermissionSerializer(BaseSerializer):
        url = serializers.HyperlinkedIdentityField(
            view_name='permission-detail',
            lookup_field="codename",
            # lookup_url_kwarg="codename",
        )
        name = serializers.CharField(max_length=255)
        codename = serializers.CharField(max_length=100)
        content_type = serializers.SlugRelatedField(
            read_only=True,
            slug_field="app_label"
        )
        related_fields = dict(
            user_set=dict(
                text=serializers.HyperlinkedRelatedField(
                    view_name='user-detail', many=True,
                    queryset=User.objects.get_queryset(),
                    lookup_field="username",
                    required=False,
                ),
                json=serializers.StringRelatedField(many=True),
                yaml=serializers.StringRelatedField(many=True),
            ),
            group_set=dict(
                text=serializers.HyperlinkedRelatedField(
                    view_name='group-detail', many=True,
                    queryset=Group.objects.get_queryset(),
                    lookup_field="name",
                    required=False, ),
                json=serializers.StringRelatedField(many=True),
                yaml=serializers.StringRelatedField(many=True),
            ),
        )
    
        class Meta:
            model = Permission
            fields = (
                'name', 'codename', 'content_type', 'url'
            )
    

    测试可行,还有其他好用的方法吗?
    或者说我这个方法符合 REST 的风格吗?

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2874 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 11:11 · PVG 19:11 · LAX 03:11 · JFK 06:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.