11import pycountry
22import rest_framework.exceptions
3+ import rest_framework.serializers
34
45import user.models
56
@@ -25,47 +26,67 @@ def __call__(self, value):
2526 raise exc
2627
2728
28- class OtherFieldValidator:
29+ class OtherFieldValidator(rest_framework.serializers.Serializer) :
2930 """
30- Validator for JSON fields containing :
31- - age (required, integer between 0 and 100)
32- - country (required, string with an ISO 3166-1 alpha-2 country code )
31+ Validates JSON fields:
32+ - age (required, 0- 100)
33+ - country (required, valid ISO 3166-1 alpha-2)
3334 """
3435
35- error_messages = {
36- 'invalid_type': 'Must be a JSON object.',
37- 'missing_field': 'This field is required.',
38- 'age_type': 'Must be an integer.',
39- 'age_range': 'Must be between 0 and 100.',
40- 'country_format': 'Must be a 2-letter ISO code.',
41- 'country_invalid': 'Invalid ISO 3166-1 alpha-2 country code.',
42- }
36+ country_codes = {c.alpha_2 for c in pycountry.countries}
37+
38+ age = rest_framework.serializers.IntegerField(
39+ required=True,
40+ min_value=0,
41+ max_value=100,
42+ error_messages={
43+ 'required': 'This field is required.',
44+ 'invalid': 'Must be an integer.',
45+ 'min_value': 'Must be between 0 and 100.',
46+ 'max_value': 'Must be between 0 and 100.',
47+ },
48+ )
49+
50+ country = rest_framework.serializers.CharField(
51+ required=True,
52+ max_length=2,
53+ min_length=2,
54+ error_messages={
55+ 'required': 'This field is required.',
56+ 'blank': 'Must be a 2-letter ISO code.',
57+ 'max_length': 'Must be a 2-letter ISO code.',
58+ 'min_length': 'Must be a 2-letter ISO code.',
59+ },
60+ )
61+
62+ def validate_country(self, value):
63+ country = value.upper()
64+ if country not in self.country_codes:
65+ raise rest_framework.serializers.ValidationError(
66+ 'Invalid ISO 3166-1 alpha-2 country code.',
67+ )
68+
69+ return country
4370
4471 def __call__(self, value):
4572 if not isinstance(value, dict):
46- raise rest_framework.exceptions .ValidationError(
47- self.error_messages['invalid_type'] ,
73+ raise rest_framework.serializers .ValidationError(
74+ {'non_field_errors': ['Must be a JSON object']} ,
4875 )
4976
50- errors = {}
51-
52- # Validate the 'age' field
53- age = value.get('age')
54- if age is None:
55- errors['age'] = self.error_messages['missing_field']
56- elif not isinstance(age, int):
57- errors['age'] = self.error_messages['age_type']
58- elif not (0 <= age <= 100):
59- errors['age'] = self.error_messages['age_range']
60-
61- # Validate the 'country' field
62- country_code = value.get('country')
63- if country_code is None:
64- errors['country'] = self.error_messages['missing_field']
65- elif not (isinstance(country_code, str) and len(country_code) == 2):
66- errors['country'] = self.error_messages['country_format']
67- elif not pycountry.countries.get(alpha_2=country_code.upper()):
68- errors['country'] = self.error_messages['country_invalid']
69-
70- if errors:
71- raise rest_framework.exceptions.ValidationError(errors)
77+ missing_fields = [
78+ field
79+ for field in self.fields
80+ if field not in value or value.get(field) in (None, '')
81+ ]
82+
83+ if missing_fields:
84+ raise rest_framework.serializers.ValidationError(
85+ {field: 'This field is required.' for field in missing_fields},
86+ )
87+
88+ serializer = self.__class__(data=value)
89+ if not serializer.is_valid():
90+ raise rest_framework.serializers.ValidationError(serializer.errors)
91+
92+ return value
0 commit comments