Возможность изменить строку кода в середине метода с помощью super () в DRF - PullRequest
0 голосов
/ 25 мая 2020

Я хочу создать подкласс следующего сериализатора:

User = get_user_model()



class UidAndTokenSerializer(serializers.Serializer):
    uid = serializers.CharField()
    token = serializers.CharField()

    default_error_messages = {
        "invalid_token": settings.CONSTANTS.messages.INVALID_TOKEN_ERROR,
        "invalid_uid": settings.CONSTANTS.messages.INVALID_UID_ERROR,
    }

    def validate(self, attrs):
        validated_data = super().validate(attrs)

        # uid validation have to be here, because validate_<field_name>
        # doesn't work with modelserializer
        try:
            uid = utils.decode_uid(self.initial_data.get("uid", ""))
            self.user = User.objects.get(pk=uid)
        except (User.DoesNotExist, ValueError, TypeError, OverflowError):
            key_error = "invalid_uid"
            raise ValidationError(
                {"uid": [self.error_messages[key_error]]}, code=key_error
            )

        is_token_valid = self.context["view"].token_generator.check_token(
            self.user, self.initial_data.get("token", "")
        )
        if is_token_valid:
            return validated_data
        else:
            key_error = "invalid_token"
            raise ValidationError(
                {"token": [self.error_messages[key_error]]}, code=key_error
            )

, чтобы использовать его метод validate (). Он полностью удовлетворяет меня, за исключением одного: я хочу изменить

self.user = User.objects.get(pk=uid)

на

self.user = User._default_manager.get(pk=uid)

Есть ли способ как-то сделать это с super(), а не копировать-вставить все это от суперкласса к подклассу? Спасибо. То, что я сделал сейчас, выглядит отрывочно ...

class CommitUndeleteUserAccountSerializer(UidAndTokenSerializer):

    def validate(self, attrs):
        User = get_user_model()
        User.objects = User._default_manager
        attrs = super().validate(attrs)
        if not self.user.deleted:
            raise serializers.ValidationError(
                *error_codes.NOT_SOFT_DELETED
            )
        return attrs

Это работает, но может быть опасно.

1 Ответ

1 голос
/ 25 мая 2020

Вы можете определить специальный метод для получения экземпляра пользователя:



class UidAndTokenSerializer(serializers.Serializer):
    uid = serializers.CharField()
    token = serializers.CharField()

    default_error_messages = {
        "invalid_token": settings.CONSTANTS.messages.INVALID_TOKEN_ERROR,
        "invalid_uid": settings.CONSTANTS.messages.INVALID_UID_ERROR,
    }

    def _get_user(self, uid):
        return get_user_model().objects.get(pk=uid)

    def validate(self, attrs):
        validated_data = super().validate(attrs)

        # uid validation have to be here, because validate_<field_name>
        # doesn't work with modelserializer
        try:
            uid = utils.decode_uid(self.initial_data.get("uid", ""))
            self.user = self._get_user(uid=uid)
        except (User.DoesNotExist, ValueError, TypeError, OverflowError):
            key_error = "invalid_uid"
            raise ValidationError(
                {"uid": [self.error_messages[key_error]]}, code=key_error
            )

        is_token_valid = self.context["view"].token_generator.check_token(
            self.user, self.initial_data.get("token", "")
        )
        if is_token_valid:
            return validated_data
        else:
            key_error = "invalid_token"
            raise ValidationError(
                {"token": [self.error_messages[key_error]]}, code=key_error
            )

и во втором классе переопределить только этот метод:


class CommitUndeleteUserAccountSerializer(UidAndTokenSerializer):
    def _get_user(self, uid):
        return get_user_model()._default_manager.get(pk=uid)

    def validate(self, attrs):
        attrs = super().validate(attrs)
        if not self.user.deleted:
            raise serializers.ValidationError(
                *error_codes.NOT_SOFT_DELETED
            )
        return attrs

без всех этих опасных танцев с менеджером

...