2013-09-15 3 views
6

В моей модели профиля User я включил поле show_email явно. Таким образом, чтобы добавить эту функцию в моей API, класс UserSerializer выглядит следующим образом:Динамически включать или исключать поля класса Serializer

class UserSerializer(serializers.ModelSerializer): 
    email = serializers.SerializerMethodField('show_email') 

    def show_email(self, user): 
     return user.email if user.show_email else None 

    class Meta: 
     model = django.contrib.auth.get_user_model() 
     fields = ("username", "first_name", "last_name", "email") 

Но мне не очень нравится. Я думаю, что было бы намного чище, если поле email было бы полностью исключено из выхода сериализатора show_email - False, вместо этого показывающее это уродливое "email": null вещь.

Как я мог это сделать?

ответ

3

Вы можете сделать это в своем представлении API, переопределив метод, возвращающий ответ, т. Е. «Глагол» представления API. Например, в ListAPIView вы бы переопределить get():

class UserList(generics.ListAPIView): 
    model = django.contrib.auth.get_user_model() 
    serializer_class = UserSerializer 

    def get(self, request, *args, **kwargs): 
     response = super(UserList, self).get(request, *args, **kwargs) 
     for result in response.data['results']: 
      if result['email'] is None: 
       result.pop('email') 
     return response 

Вы, вероятно, хотите добавить еще некоторые проверки атрибутов, но это суть того, как это может быть сделано. Кроме того, я бы добавил, что удаление полей из некоторых результатов может вызвать проблемы для приложения-потребителя, если он ожидает, что они будут присутствовать для всех записей.

0

Вы можете переопределить метод restore_fields для сериализатора. Здесь, в методе restore_fields, вы можете изменить список полей - serializer.fields - поп, нажать или изменить любое из полей.

например: поле рабочего пространства read_only, когда действие не «создать»

class MyPostSerializer(ModelSerializer): 

def restore_fields(self, data, files): 
    if (self.context.get('view').action != 'create'): 
     self.fields.get('workspace').read_only=True 
    return super(MyPostSerializer, self).restore_fields(data, files) 

class Meta: 
    model = MyPost 
    fields = ('id', 'name', 'workspace') 
+0

Это, кажется, ответ OBSOLETE. В версии 3.2.1 по крайней мере нет метода 'restore_fields'. Вероятно, теперь лучший способ - использовать отдельные сериализаторы, применяемые в get_serializer view/set. И для этого отдельные сериализаторы используют наследование и в Meta modify через extra_kwargs, если что-то необходимо. – andi

1

Этот ответ приходит поздно, но и для будущих поисков Google: есть пример в документации о Dynamically modifying fields. Таким образом, путем передачи аргумента сериализатором, вы контролируете ли не обрабатывается поле:

serializer = MyPostSerializer(posts, show_email=permissions) 

, а затем в инициализации функции в сериализатором вы можете сделать что-то вроде:

class MyPostSerializer(serializers.ModelSerializer): 

def __init__(self, *args, **kwargs): 
    show_email = kwargs.pop('show_email', None) 

    # Instantiate the superclass normally 
    super(DeviceSerializer, self).__init__(*args, **kwargs) 

    if not show_email: 
     self.fields.pop("show_email") 

Теперь поле сериализатора игнорируется полем show_email.

+0

Дайте ему попробовать, он не работает. Это работает для полей экземпляра (поля модели) 'enail' является дополнительным полем, указанным, вам нужно удалить его для m' ._data', что не является допустимым выбором (как следует из названия). –

Смежные вопросы