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

2021-11-19 18:04:57 +08:00
 firejoke

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 的风格吗?

1560 次点击
所在节点    Django
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/816614

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX