V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
firejoke
V2EX  ›  Django

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

  •  
  •   firejoke · Nov 19, 2021 · 2472 views
    This topic created in 1626 days ago, the information mentioned may be changed or developed.

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

    No Comments Yet
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   952 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 18:11 · PVG 02:11 · LAX 11:11 · JFK 14:11
    ♥ Do have faith in what you're doing.