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")
首先你需要创建一个类,并从这个类继承你的序列化器,如下所示:
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