Расширьте Django Rest framework, чтобы разрешить наследование контекста во вложенных сериализаторах
Я использую Django 1.6 (очень скоро обновление до 1.8), Python 2.7 и DRF 3.2.5 (очень скоро обновление до последней версии).
у меня есть набор вложенных сериализаторы (~10 уровней, в общей сложности 20-30 моделей, которые сериализуются). Я пытаюсь добавить логический флаг в контекст, который определит, будет ли сериализованная выходная иерархия детализирована (включая поля всех моделей) или базовая (только часть полей).
Я написал следующий код (частичное фрагмент):
from rest_framework import serializers
from app.models import Institute, Department, Member
class MemberSerializer(serializers.ModelSerializer):
def get_fields(self):
fields = super(MemberSerializer, self).get_fields()
if self.context['basic_view']:
for field in ['height', 'weight']:
del fields[field]
return fields
class Meta:
model = Member
fields = ('id', 'birth_date', 'height', 'weight')
class DepartmentSerializer(serializers.ModelSerializer):
members = MemberSerializer(many=True, read_only=True)
def get_fields(self):
fields = super(DepartmentSerializer, self).get_fields()
if self.context['basic_view']:
for field in ['type', 'manager']:
del fields[field]
return fields
class Meta:
model = Department
fields = ('id', 'name', 'type', 'manager', 'members')
class InstituteSerializer(serializers.ModelSerializer):
departments = DepartmentSerializer(many=True, read_only=True)
def get_fields(self):
fields = super(InstituteSerializer, self).get_fields()
if self.context['basic_view']:
for field in ['name', 'type']:
del fields[field]
return fields
class Meta:
model = Institute
fields = ('id', 'name', 'type', 'departments')
def get_entities(is_basic_view):
institutes_list = Institute.objects.all()
serializer = InstituteSerializer(institutes_list, many=True, read_only=True, context={'basic_view': is_basic_view})
return serializer.data
но затем выяснилось, что "контекст", который передается из "get_entities" в "InstituteSerializer", не передается вложенным сериализаторам. Это означает, что в приведенном выше примере - InstituteSerializer имеет "basic_view" в "контексте", но MemberSerializer & DepartmentSerializer нет.
Я нашел рабочее решение в контекст во вложенных сериализаторах django Rest framework: использовать SerializerMethodField для каждого вложенного поля (например 'departments'), и в методе 'get_' вручную передать контекст. Моя проблема с этим решением заключается в том, что он требует встраивания этого кода 20-30 раз в мой код, в конечном итоге удваивая количество исходных строк.
мой запрос-если у кого-то есть (или может помочь реализовать) расширение для сериализаторов.ModelSerializer, который получит дополнительный параметр при построении, например "inherit_context". Тогда единственное, что мне нужно будет изменить в моих классах, например в "InstituteSerializer", является добавлением этого параметра:
class InstituteSerializer(serializers.ModelSerializer):
departments = DepartmentSerializer(many=True, read_only=True, inherit_context=True)
def get_fields(self):
fields = super(InstituteSerializer, self).get_fields()
if self.context['basic_view']:
for field in ['name', 'type']:
del fields[field]
return fields
class Meta:
model = Institute
fields = ('id', 'name', 'type', 'departments')
1 ответов
видимо я что-то пропустил... "Контекст"уже унаследовал вплоть до вложенных сериализаторов...
однако, причина, по которой это не сработало для меня, заключается в том, что в рамках моего вложенности некоторые из дочерних сериализаторов были определены через сериализаторы.SerializerMethodField(). И в таком случае (только!) контекст не автоматически наследуется.
решение состоит в том, чтобы просто передать "контекст", внутри в 'get_...'метод, связанный с каждым SerializerMethodField:
class ParentSerializer(serializers.ModelSerializer):
child = serializers.SerializerMethodField()
def get_child(self, obj):
child = ....
serializer = ChildSerializer(instance=child, context=self.context)
return serializer.data
P. S-проблема DRF github, подобная моей, была создана некоторое время назад:https://github.com/tomchristie/django-rest-framework/issues/2555