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