Django Rest Framework - 如何为所有 ModelSerializer 字段创建自定义错误消息?
Posted
技术标签:
【中文标题】Django Rest Framework - 如何为所有 ModelSerializer 字段创建自定义错误消息?【英文标题】:Django Rest Framework - how to create custom error messages for all ModelSerializer fields? 【发布时间】:2015-08-14 10:24:52 【问题描述】:这是我的 serializers.py(我想为内置的 User 模型创建一个序列化器):
from rest_framework import serializers
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'password', 'email', )
我知道 Django Rest Framework 有它自己的字段验证器,因为当我尝试使用已经存在的用户名创建用户时,它会引发错误提示:
'username': [u'This field must be unique.']
我想自定义错误消息并使其显示“此用户名已被占用。请重试”而不是“此字段必须是唯一的”。
它还有一个内置的正则表达式验证器,因为当我创建一个带有感叹号的用户名时,它会说:
'username': [u'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.']
我想自定义正则表达式验证器,让它只显示“无效的用户名”。
如何自定义每个字段的所有错误消息?
注意:根据这个帖子:Custom error messages in Django Rest Framework serializer我可以做到:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
def __init__(self, *args, **kwargs):
super(UserSerializer, self).__init__(*args, **kwargs)
self.fields['username'].error_messages['required'] = u'My custom required msg'
但是对于“唯一”和“正则表达式”验证器,我该怎么办?我试过做
self.fields['username'].error_messages['regex'] = u'My custom required msg'
和
self.fields['username'].error_messages['validators'] = u'My custom required msg'
但都没有用。
【问题讨论】:
【参考方案1】:您也可以只自定义您的语言翻译,请看这里:
https://docs.djangoproject.com/en/3.2/topics/i18n/translation/#message-files
您所要做的就是创建消息文件,在其中更改翻译并将您的消息编译成 .mo 文件。
这种方法并不像我想象的那样不可接受。看这里:
https://www.django-rest-framework.org/topics/internationalization/
DRF 文档说,它的常见做法是通过翻译自定义错误消息(您自己的和默认的)。
我对那些想尝试上述路径的人的建议:
-
制作默认的 django.po 文件。大多数默认错误都会出现。
如果您使用的是 DRF,请打开此文件 https://raw.githubusercontent.com/encode/django-rest-framework/master/rest_framework/locale/en_US/LC_MESSAGES/django.po ,选择您要自定义的错误,然后仅将该错误复制到上面的 django.po 文件中。
自定义它。
编译它。
(!) 注意确保您的翻译文件完全命名为 django.po,而不是 mylovelydjango.po,不是 myproject.po,而是完全命名为 django.po,否则将不起作用。
【讨论】:
【参考方案2】:为了替换唯一或正则表达式错误消息,您应该更改相应验证器对象的message
成员。这可以使用单独的 mixin 类来完成:
from django.core.validators import RegexValidator
from rest_framework.validators import UniqueValidator
from django.utils.translation import ugettext_lazy as _
class SetCustomErrorMessagesMixin:
"""
Replaces built-in validator messages with messages, defined in Meta class.
This mixin should be inherited before the actual Serializer class in order to call __init__ method.
Example of Meta class:
>>> class Meta:
>>> model = User
>>> fields = ('url', 'username', 'email', 'groups')
>>> custom_error_messages_for_validators =
>>> 'username':
>>> UniqueValidator: _('This username is already taken. Please, try again'),
>>> RegexValidator: _('Invalid username')
>>>
>>>
"""
def __init__(self, *args, **kwargs):
# noinspection PyArgumentList
super(SetCustomErrorMessagesMixin, self).__init__(*args, **kwargs)
self.replace_validators_messages()
def replace_validators_messages(self):
for field_name, validators_lookup in self.custom_error_messages_for_validators.items():
# noinspection PyUnresolvedReferences
for validator in self.fields[field_name].validators:
if type(validator) in validators_lookup:
validator.message = validators_lookup[type(validator)]
@property
def custom_error_messages_for_validators(self):
meta = getattr(self, 'Meta', None)
return getattr(meta, 'custom_error_messages_for_validators', )
然后你可以继承这个 mixin 并更新 Meta
类:
class UserSerializer(SetCustomErrorMessagesMixin, serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'email', 'groups')
custom_error_messages_for_validators =
'username':
UniqueValidator: _('This username is already taken. Please, try again'),
RegexValidator: _('Invalid username')
【讨论】:
另一种方法是使用Meta.extra_kwargs
字段替换字段的所有验证器。请注意,您应该提供 all 验证器,因为它将替换 all 原始验证器。如果性能很重要,您应该提供一些附加信息,至少 - 预期的每秒连接数。但是如果你想替换,比如 10 条甚至 100 条消息,你不会看到建议的方法之间有任何区别。
HyperlinkedModelSerializer
的行为类似于 ModelSerializer
,但它表示超链接而不是 id。只是风格问题。
我总是将 mixins 放入 mixins
模块(如 views
、models
等)。
是的,你可以。 SetCustomErrorMessagesMixin
不依赖于序列化器类型
好像我忘了添加所需的导入,抱歉。我已经更新了答案,请看一下。以上是关于Django Rest Framework - 如何为所有 ModelSerializer 字段创建自定义错误消息?的主要内容,如果未能解决你的问题,请参考以下文章
Django Rest Framework api如何为所有人添加身份验证权限
如何处理 django-rest-framework 中 url 模式中的外键关系
Django REST Framework:如何用空字符串替换 null?
Django Rest Framework:在 ViewSet 上打开分页(如 ModelViewSet 分页)