Django REST Framework: Есть ли у ModelSerializer возможность динамического изменения полей с помощью GET или (POST, PUT, DELETE)?
Есть ли у ModelSerializer возможность динамического изменения полей с помощью GET или (POST, PUT, DELETE)?
В то время как для GET требуются сложные поля, такие как вложенные сериализаторы, они не требуются для (POST, PUT, DELETE).
Я думаю, что решение состоит в том, чтобы использовать отдельные сериализаторы для GET и (POST, PUT, DELETE). Но в этом случае мне придется создать довольно много бесполезных сериализаторов. Есть ли какое-нибудь хорошее решение?
сначала нужно создать класс и унаследовать от него свой сериализатор, как показано ниже:
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