Django REST Framework:ModelSerializer 是否可以选择通过 GET 或 (POST, PUT, DELETE) 动态更改字段?

Django REST Framework: Does ModelSerializer have an option to change the fields dynamically by GET or (POST, PUT, DELETE)?

ModelSerializer 是否可以选择通过 GET 或(POST、PUT、DELETE)动态更改字段?

虽然 GET 需要复杂的字段,例如嵌套序列化程序,但 (POST、PUT、DELETE) 不需要这些。

我认为解决方案是为 GET 和(POST、PUT、DELETE)使用单独的序列化程序。 但在那种情况下,我将不得不创建很多无用的序列化程序。 有什么好的解决办法吗?

class PlaylistSerializer(serializers.ModelSerializer):
    user = UserDetailSerializer(read_only=True)
    tracks = serializers.SerializerMethodField()
    is_owner = serializers.SerializerMethodField()
    is_added = serializers.SerializerMethodField()
    is_favorited = serializers.BooleanField()

    class Meta:
        model = Playlist
        fields = (
            "pk",
            "user",
            "title",
            "views",
            "is_public",
            "is_wl",
            "created_at",
            "updated_at",
            "tracks",
            "is_owner",
            "is_added",
            "is_favorited",
        )

    def get_is_owner(self, obj):
        return obj.user == self.context["request"].user

    def get_tracks(self, obj):
        queryset = obj.track_set
        if queryset.exists():
            tracks = TrackSerializer(queryset, context=self.context, many=True).data
            return tracks
        else:
            return []

    def get_is_added(self, obj):
        try:
            return obj.is_added
        except AttributeError:
            return False


class PlaylistUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Playlist
        fields = ("title", "is_public")

首先您需要创建一个 class 并从此 class 继承您的序列化程序,如下所示:

from rest_framework import serializers


class DynamicFieldsModelSerializer(serializers.ModelSerializer):
    """To be used alongside DRF's serializers.ModelSerializer"""
    @classmethod
    def default_fieldset(cls):
       return cls.Meta.fields

    def __init__(self, *args, **kwargs):
        self.requested_fields = self._extract_fieldset(**kwargs)
        # Fields should be popped otherwise next line complains about 
unexpected kwarg
        kwargs.pop('fields', None)
        super().__init__(*args, **kwargs)
        self._limit_fields(self.requested_fields)

    def _extract_fieldset(self, **kwargs):
        requested_fields = kwargs.pop('fields', None)
        if requested_fields is not None:
            return requested_fields

        context = kwargs.pop('context', None)
        if context is None:
            return None

        return context.get('fields')

    def _limit_fields(self, allowed_fields=None):
        if allowed_fields is None:
            to_exclude = set(self.fields.keys()) - set(self.default_fieldset())
        else:
            to_exclude = set(self.fields.keys()) - set(allowed_fields)
        for field_name in to_exclude or []:
            self.fields.pop(field_name)

    @classmethod
    def all_fields_minus(cls, *removed_fields):
        return set(cls.Meta.fields) - set(removed_fields)

那么你的序列化程序将是这样的:

class PlaylistSerializer(DynamicFieldsModelSerializer):
    class Meta:
        model = Playlist
        fields = ("pk", "user", "title", "views", "is_public",
        "is_wl", "created_at", "updated_at", "tracks", "is_owner",
        "is_added", "is_favorited",)

    @classmethod
    def update_serializer(cls):
        return ("title", "is_public")
    
    @classmethod
    def view_serializer(cls):
        return ("title", "is_public", "is_owner", "is_added")

然后你将调用你的序列化程序如下:

PlaylistSerializer(instance, fields=PlaylistSerializer.update_serializer()).data