有什么方法可以生成对drf中请求的标准响应消息

时间:2019-02-10 07:10:30

标签: django django-rest-framework

我正在使用Django DRF构建api。该API工作正常。但是它针对不同类型的错误生成不同的响应。假设,如果我添加了用户注册功能。我正在使用serializers.ValidationError函数处理序列化程序中的一些错误。但这改变了对不同错误的响应。我只希望以{"message": "reason for the error", "error": 1}的标准方式进行回复。我不想硬编码它。我的意思是我已经使用了多种功能,所以我必须对所有地方进行硬编码。因此,有没有更好的解决方案,例如向序列化器添加函数并从中生成响应?

class UserSerializer(serializers.ModelSerializer):

    confirm_password = serializers.CharField(max_length=50, required=True, validators=[password_check], write_only=True)
    password = serializers.CharField(max_length=50, required=True, validators=[password_check])
    Id = serializers.CharField(max_length=100, required=False, allow_blank=True)
    user_type = serializers.CharField(max_length=30, required=True, write_only=True)
    email = serializers.EmailField(required=True)

    def validate_username(self, username):
        if User.objects.filter(username=username):
            raise serializers.ValidationError('Username already chosen!')

        if len(username) < 8:
            raise serializers.ValidationError('Username min length is 8')
        return username

    def validate_email(self, email):
        try:
            validate_email(email)
        except ValidationError:
            raise serializers.ValidationError('Enter a valid email')

        if User.objects.filter(email=email):
            raise serializers.ValidationError('Email already chosen!')
        return email

    def validate(self, attrs):
        key = 0
        try:
            if models.Profile.objects.filter(userid=attrs['Id']).exists() and attrs['Id'] != '':
                raise serializers.ValidationError('UserId already chosen')
            if attrs['Id'] == '':
                key=1
        except KeyError:
                key=1

        if key == 1:
            if attrs['user_type'] != 'Admin' and attrs['user_type'] != 'AdminCoordinate':
                raise serializers.ValidationError("UserId can\'t be empty!")
            else:
                attrs['user_id'] = ''

        if attrs['password'] != attrs['confirm_password']:
            raise serializers.ValidationError('Enter same passwords both the times!')
        return attrs

    class Meta:
        model = User
        fields = ('pk', 'username', 'password', 'email', 'confirm_password', 'Id', 'user_type')
        read_only_fields = ('pk',)

2 个答案:

答案 0 :(得分:0)

对此没有简单的方法,至少没有您想要的那么简单。

  • 您也许可以编写一个中间件来处理此问题,但这仍然有些混乱,因为您必须检查响应中的每个错误并覆盖它们。我真的不建议这样做。

  • 您还可以为每个序列化器使用Meta类,但是仍然需要为每个序列化器添加一些代码。

示例:

class SomeSerializer(ModelSerializer):

    class Meta:
        model = SomeMode
        extra_kwargs = {"SomeField": {"error_messages": {"required": "This field can not be empty!"}}}

最后,我认为您最终将对大多数验证进行硬编码。

答案 1 :(得分:0)

感谢@ Navid2zp的回答。这太酷了。但是它不能处理所有异常。我仔细阅读了文档,发现了一种处理所有异常的简单通用方法。我编写了一个简单的代码,使用该代码一次只能显示一个错误,而不是显示多个错误。这是我的编码方式:

from rest_framework.views import exception_handler


def custom_exception_handler(exc, content):

    response = exception_handler(exc, content) # Get the response Header.
    error = ''
    for key, value in response.data.items():
        if isinstance(value, str):
            error = value
        else:
            error = value[0]
        if key == 'non_field_errors':
            custom_response = {'message': error, 'error': 1}
        else:
            custom_response = {'message': key + ", " +  error, 'error': 1}
        break
    response.data = custom_response
    return response

我写了一个自定义的异常处理程序来显示消息,并且该类也必须添加到REST_FRAMEWORK内的settings.py文件中。

'EXCEPTION_HANDLER': 'project_name.utils.custom_exception_handler',