Skip to content

Commit 4ce2d22

Browse files
refactor: Rework the validator for the other field and its age and country fields.
2 parents 2f624d0 + 76d6d78 commit 4ce2d22

File tree

4 files changed

+61
-39
lines changed

4 files changed

+61
-39
lines changed

.flake8

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[flake8]
22
max-line-length = 79
3-
application_import_names = promo_code, user
3+
application_import_names = promo_code, user, core
44
import-order-style = google
55
exclude = */migrations/, venv/, verdict.py, .venv/, env/, venv, .git, __pycache__
66
max-complexity = 10

.isort.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[settings]
22
profile = black
33
skip = migrations, venv/, venv
4-
known_first_party = promo_code, user
4+
known_first_party = promo_code, user, core
55
default_section = THIRDPARTY
66
force_sort_within_sections = true
77
line_length = 79

promo_code/core/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import core.views
21
import django.urls
32

3+
import core.views
4+
45
app_name = 'api-core'
56

67

promo_code/user/validators.py

Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pycountry
22
import rest_framework.exceptions
3+
import rest_framework.serializers
34

45
import 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

Comments
 (0)