1
1
import pycountry
2
2
import rest_framework .exceptions
3
+ import rest_framework .serializers
3
4
4
5
import user .models
5
6
@@ -25,47 +26,67 @@ def __call__(self, value):
25
26
raise exc
26
27
27
28
28
- class OtherFieldValidator :
29
+ class OtherFieldValidator ( rest_framework . serializers . Serializer ) :
29
30
"""
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)
33
34
"""
34
35
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
43
70
44
71
def __call__ (self , value ):
45
72
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' ]} ,
48
75
)
49
76
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