Метод PATCH не работает в Django ModelViewSet - PullRequest
0 голосов
/ 19 апреля 2020

У меня проблемы с использованием patch метода внутри ModelViewSet для моей пользовательской модели User. Вот код:

views.py

@permission_classes([IsAdminUser])
    class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    http_method_names = ['get', 'post', 'patch', 'head', 'delete']

serializers.py

class UserSerializer(serializers.ModelSerializer):
class Meta:
    model = User
    fields = ('id',
              'email',
              'password',
              'is_active',
              'is_staff',
              'is_admin')
    extra_kwargs = {'password': {'write_only': True, 'required': True},
                    'is_active': {'default': True},
                    'is_staff': {'default': False},
                    'is_admin': {'default': False}}

def create(self, validated_data):
    self.is_valid(raise_exception=True)
    if validated_data['is_admin']:
        validated_data['is_staff'] = True
    user = User.objects.create_user(**validated_data)
    return user

def update(self, instance, validated_data):
    instance.email = validated_data.get('email')
    instance.is_active = validated_data.get('is_active')
    instance.is_staff = validated_data.get('is_staff')
    instance.is_admin = validated_data.get('is_admin')
    if instance.is_admin:
        instance.is_staff = True
    instance.save()
    return instance

Я установил разрешение для того, чтобы разрешить только суперпользователю доступ к этому представлению. Проблема возникает при попытке выполнить патч. Например, если я попытаюсь изменить атрибут is_staff на Ложь для пользователя, использующего Почтальон с PATCH, и "http://localhost: 8000 / users / USER_ID ", Я получаю следующую ошибку:

django .db.utils.IntegrityError: нулевое значение в столбце «электронная почта» нарушает ненулевое ограничение ПОДРОБНОЕ ОПИСАНИЕ tCQ9zZk1uOdJD2F7L9BQRFFDbz1GXJ ..., 2020-04-18 20: 02: 57.052639 + 00, null, t, t, t).

Похоже, django просит меня предоставить каждое поле для Модель пользователя ( email , is_active , is_staff , is_admin ), который, по моему мнению, не имеет смысла, что это PATCH запрос. Чтобы решить эту проблему, я изменил метод update моего UserSerializer следующим образом:

    def update(self, instance, validated_data):
        if validated_data.get('email') is not None:
            instance.email = validated_data.get('email')
        if validated_data.get('is_active') is not None:
            instance.is_active = validated_data.get('is_active')
        if validated_data.get('is_staff') is not None:
            instance.is_staff = validated_data.get('is_staff')
        if validated_data.get('is_admin') is not None:
            instance.is_admin = validated_data.get('is_admin')
        if instance.is_admin:
            instance.is_staff = True
        instance.save()
        return instance

Это работает сейчас, но я хотел бы знать хорошее ли это решение На мой взгляд, это не «канонический» способ решения проблемы. Я также пытался переопределить метод partal_update (следуя ответам других StackOverflow) внутри моего UserViewSet, без результатов.

1 Ответ

0 голосов
/ 19 апреля 2020

Я нашел очень полезным этот предыдущий пост django -rest-framework-serializer-update-method-does-not-save-object Проблема была в сериализаторе. Я изменил перезаписанный метод update внутри моего UserSerializer , и теперь PATCH работает

def update(self, instance, validated_data):
    if validated_data.get('is_admin'):
        validated_data['is_staff'] = True
    return super().update(instance, validated_data)

ПРИМЕЧАНИЕ: нет необходимости переопределять какой-либо метод в представлении, просто добавьте 'patch' to http_method_names list

...