Package: drf-friendly-errors-django-4
Extension for Django REST framework error displayFork From:https://github.com/FutureMind/drf-friendly-errorsAdded support for django >= 4.0OverviewThis package extends default error JSON body providing configurable error codes
and more consumable response structure.It turns default JSON body of HTTP 400 response, which look like this{"name":["This field is required."],"password":["This field may not be blank."]"age":["This field may not be null."]"description":["Ensure this field has no more than 100 characters."]}into{"code":1001,"message":"Validation Failed","errors":[{"code":2002,"field":"name","message":"This field is required."},{"code":2031,"field":"password","message":"This field may not be blank."},{"code":2023,"field":"age","message":"This field may not be null."},{"code":2041,"field":"description","message":"Ensure this field has no more than 100 characters."},]}Library handles allDjango REST frameworkbuilt-in serializer validation.RequirementsPython (3.6, 3.7, 3.8-dev)Django (1.11, 2.0, 2.1, 2.2, 2.2.5)Django REST framework (3.7, 3.8, 3.9, 3.10)InstallationBy running installation script$pythonsetup.pyinstallOr using pip (pendent register xD)$pipinstalldrf-friendly-errorsUsageSimply add a FriendlyErrorMessagesMixin to your serializer or model serializer classfromrest_framework_friendly_errors.mixinsimportFriendlyErrorMessagesMixinclassMySerializer(FriendlyErrorMessagesMixin,ModelSerializer):If you want to change default library settings and provide your own set of error codes just add following in your
settings.pyFRIENDLY_ERRORS={FIELD_ERRORS={'CharField':{'required':10,'null':11,'blank':12,'max_length':13,'min_length':14}}VALIDATOR_ERRORS={'UniqueValidator':50},EXCEPTION_DICT={'PermissionDenied':100}}Custom serializer validationIf you need custom field validation or validation for whole serializer register your validation in serializer classclassPostSerializer(FriendlyErrorMessagesMixin,serializers.ModelSerializer):classMeta:model=Postdefvalidate_title(self,value):ifvalue[0]!=value[0].upper():raiseValidationError('First letter must be an uppercase')returnvaluedefvalidate(self,attrs):category=attrs.get('category)title=attrs.get('title')ifcategoryandcategorynotintitle:raiseValidationError('Title has to include category')returnattrsFIELD_VALIDATION_ERRORS={'validate_title':5000}# register your own validation method and assign it to error codeNON_FIELD_ERRORS={'Title has to include category':8000}# register non field error messages and assign it to error codeIf you want to raise field error in validate method use register_error method provided by a mixinclassPostSerializer(FriendlyErrorMessagesMixin,serializers.ModelSerializer):classMeta:model=Postdefvalidate(self,attrs):category=attrs.get('category')title=attrs.get('title')ifcategoryandcategorynotintitle:self.register_error(error_message='Title has to include category',error_code=8000,field_name='title')returnattrsError codes not related to serializer validationTo turn other type of errors responses into friendly errors responses with error codes
add this exception handler to your REST_FRAMEWORK settingsREST_FRAMEWORK={'EXCEPTION_HANDLER':'rest_framework_friendly_errors.handlers.friendly_exception_handler'}Default error codesFollowing conventions were used:1xxx - Are reserved for non field errors2xxx - Are reserved for field errors3xxx - Are reserved for validator errors4xxx - Are reserved for other errors not related to serializer validationDefault field error codesField is required2001: BooleanField, NullBooleanField2002: CharField, EmailField, RegexField, SlugField, URLField, UUIDField, FilePathField, IPAddressField2003: IntegerField, FloatField, DecimalField2004: ChoiceField, MultipleChoiceField2005: FileField, ImageField2006: ListField, DictField, JSONField2007: StringRequiredField, PrimaryKeyRelatedField, HyperlinkedRelatedField, SlugRelatedField, HyperlinkedIdentityField, ManyRelatedField2008: ReadOnlyField, HiddenField, ModelField, SerializerMethodFieldField data is invalid (invalid regex, string instead of number, date, etc.)2011: BooleanField, NullBooleanField2012: EmailField, RegexField, SlugField, URLField, UUIDField, IPAddressField2013: IntegerField, FloatField, DecimalField2014: FileField, ImageField2015: DateTimeField, DateField, TimeField, DurationFieldField data cannot be null2021: BooleanField, NullBooleanField2022: CharField, EmailField, RegexField, SlugField, URLField, UUIDField, FilePathField, IPAddressField2023: IntegerField, FloatField, DecimalField2024: ChoiceField, MultipleChoiceField2025: FileField, ImageField2026: ListField, DictField, JSONField2027: StringRequiredField, PrimaryKeyRelatedField, HyperlinkedRelatedField, SlugRelatedField, HyperlinkedIdentityField, ManyRelatedField2028: ReadOnlyField, HiddenField, ModelField, SerializerMethodFieldField data cannot be blank2031: CharField, EmailField, RegexField, SlugField, URLField, UUIDField, IPAddressFieldField data is too long string2041: CharField, EmailField, RegexField, SlugField, URLField, UUIDField, IPAddressField2042: IntegerField, FloatField, DecimalField2043: FileField, ImageFieldField data is too short string2051: CharField, EmailField, RegexField, SlugField, URLField, UUIDField, IPAddressFieldField data is too big number2061: IntegerField, FloatField, DecimalFieldField data is too small number2071: IntegerField, FloatField, DecimalFieldField data do not match any value from available choices2081: ChoiceField, MultipleChoiceField2082: FilePathField2083: ManyRelatedFieldField is empty2091: FileField, ImageField2092: MultipleChoiceField2093: ManyRelatedFieldFile has no name2101: FileField, ImageFieldFile is an invalid image2111: ImageFieldField is not a list2121: MultipleChoiceField2122: ListField2123: ManyRelatedFieldField is not a dict2131: DictFieldField is not a json2141: JSONFieldField does not exist (invalid hyperlink, primary key, etc.)2151: PrimaryKeyRelatedField, HyperlinkedRelatedField, SlugRelatedField, HyperlinkedIdentityFieldIncorrect type for relation key2161: PrimaryKeyRelatedField, HyperlinkedRelatedField, SlugRelatedField, HyperlinkedIdentityFieldCouldn’t match url or name to a view2171: HyperlinkedRelatedField, HyperlinkedIdentityFieldExpected a DateTime, got Date2181: DateTimeFieldExcpected a Date, got DateTime2191: DateFieldToo many digits for defined Decimal2201: DecimalFieldToo many whole digits for defined Decimal2211: DecimalFieldToo many decimal digits for defined Decimal2221: DecimalFieldDefault built-in validators error codesUniqueValidator: 3001UniqueTogetherValidator: 3003UniqueForDateValidator: 3004UniqueForMonthValidator: 3004UniqueForYearValidator: 3005RegexValidator: 3006EmailValidator: 3007URLValidator: 3008MaxValueValidator: 3009MinValueValidator: 3010MaxLengthValidator: 3011MinLengthValidator: 3012DecimalValidator: 3013validate_email: 3014validate_slug: 3015validate_unicode_slug: 3016validate_ipv4_address: 3017validate_ipv46_address: 3018validate_comma_separated_integer_list: 3019int_list_validator: 3020Other error codes not related to serializer validationAPI Reference - APIException :https://www.django-rest-framework.org/api-guide/exceptions/#api-referenceServer Error: 4000Parser Error (exception was raised by Parser class): 4001,Authentication Failed (invalid credentials were provided): 4002,Not Authenticated (no credentials were provided): 4003,Not Found (Http404): 4004,Permission Denied: 4005,Method Not Allowed (invalid HTTP method): 4006,Not Acceptable (Could not satisfy the request Accept header): 4007,Unsupported Media-Type: 4008,Throttled (Too many requests): 4009ValidationError: 4010TestsPull requests won’t be accepted without passing tests. You can run the test suite with:pythonruntests.pyContributorsGeoffrey Lehée <socketubs>Franky Quintero <frankyjquintero>