Django Rest Framework выбрасывает 400, прежде чем я могу обработать исключение для ModelViewSet
У меня есть модель пользователя в моем приложении с уникальным полем для email. Однако мне нужно отловить, когда пользователь пытается сделать дублирующий запрос, чтобы я мог выполнить некоторую обработку другим способом.
Я делаю вызов POST для создания этого пользователя. DRF, конечно, выбрасывает 400 с существующим сообщением электронной почты.
Но даже когда я создаю метод validate_email в своей модели или пытаюсь поймать его с помощью пользовательского исключения, он не ловится.
Я создал пользовательский ValidationError, потому что в общем ValidationError не было способа отфильтровать его, кроме общего кода, unique
, или соответствия строке сообщения.
Как я могу поймать эту специфическую валидацию в Django Rest Framework?
Сообщение об ошибке: { "email": [ "Пользователь с таким адресом электронной почты уже существует". ], "status_code": 400 }
Модель пользователя: class User(AbstractBaseUser, PermissionsMixin): """ Модель пользователя """
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
email = models.EmailField(_("email address"), unique=True)
name = models.CharField(_("name"), max_length=30, blank=True)
def validate_email(self):
email = self.email
valid_email = email is not None and email.endswith(self.email_domain)
if not valid_email:
raise ValidationError(
_("Email is not valid"),
code="invalid.email",
)
if Users.objects.filter(email=email).exists():
import ipdb; ipdb.sset_trace() #does not get called
raise EmailExists()
Код UserViewSet:
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
serializer_class = UserSerializer
permission_classes = (IsAuthenticated,)
def get_serializer_class(self):
if self.action == 'list':
return UserSerializer
else:
return UserDetailSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
except EmailExists:
logger.debug('caught the existing email')
import ipdb; ipdb.sset_trace()
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
пользовательское исключение:
from rest_framework.exceptions import ValidationError
class EmailExists(ValidationError):
"""Raised when user exists"""
pass
Ловите исключение с помощью ValidationError
try:
serializer.is_valid(raise_exception=True)
except ValidationError:
logger.debug('caught the existing email')
import ipdb; ipdb.sset_trace()
Вместо этого вам нужно перехватить исключение ValidationError
. Причина в том, что вы определили свое поле электронной почты unique=True
и Django автоматически проверит его при вызове serializer.is_valid()
.
Кроме того, вы можете проверить ошибку уникального ограничения с помощью exc. get_full_details()
try:
serializer.is_valid(raise_exception=True)
except ValidationError as exc:
errors = exc.get_full_details()
if 'email' in errors and errors['email']['code'] == 'unique':
# do something, maybe re-raise with your custom exception:
raise EmailExists from exc
Ref