Skip to content

Commit 1f012e4

Browse files
Implement region argument for serializerfields
The region argument was implemented for the database field and form field, but not the Django REST framework serializers. Align the serializer with the other fields. Add a bunch of tests for that field.
1 parent b746061 commit 1f012e4

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

phonenumber_field/serializerfields.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
1+
from django.conf import settings
12
from django.utils.translation import gettext_lazy as _
23
from rest_framework import serializers
34
from rest_framework.exceptions import ValidationError
45

5-
from phonenumber_field.phonenumber import to_python
6+
from phonenumber_field.phonenumber import to_python, validate_region
67

78

89
class PhoneNumberField(serializers.CharField):
910
default_error_messages = {"invalid": _("Enter a valid phone number.")}
1011

12+
def __init__(self, *args, region=None, **kwargs):
13+
super().__init__(*args, **kwargs)
14+
validate_region(region)
15+
self.region = region or getattr(settings, "PHONENUMBER_DEFAULT_REGION", None)
16+
1117
def to_internal_value(self, data):
1218
str_value = super().to_internal_value(data)
13-
phone_number = to_python(str_value)
19+
phone_number = to_python(str_value, region=self.region)
1420
if phone_number and not phone_number.is_valid():
1521
raise ValidationError(self.error_messages["invalid"])
1622
return phone_number

tests/test_serializers.py

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from django.test import SimpleTestCase
1+
from django.test import SimpleTestCase, override_settings
22
from rest_framework import serializers
33

4+
from phonenumber_field.phonenumber import PhoneNumber
45
from phonenumber_field.serializerfields import PhoneNumberField
56

67
from .models import OptionalPhoneNumber
@@ -25,3 +26,74 @@ class PhoneNumberSerializer(serializers.Serializer):
2526

2627
s = PhoneNumberSerializer(data={"phone": 1})
2728
self.assertIs(s.is_valid(), False)
29+
30+
def test_empty_required(self):
31+
class PhoneNumberSerializer(serializers.Serializer):
32+
phone = PhoneNumberField()
33+
34+
serializer = PhoneNumberSerializer(data={"phone": ""})
35+
self.assertIs(serializer.is_valid(), False)
36+
self.assertEqual(serializer.validated_data, {})
37+
38+
def test_empty_optional(self):
39+
class PhoneNumberSerializer(serializers.Serializer):
40+
phone = PhoneNumberField(allow_blank=True)
41+
42+
serializer = PhoneNumberSerializer(data={"phone": ""})
43+
self.assertIs(serializer.is_valid(), True)
44+
self.assertEqual(serializer.validated_data, {"phone": ""})
45+
46+
def test_e164_phone_number(self):
47+
class PhoneNumberSerializer(serializers.Serializer):
48+
phone = PhoneNumberField()
49+
50+
serializer = PhoneNumberSerializer(data={"phone": "+33612345678"})
51+
self.assertIs(serializer.is_valid(), True)
52+
self.assertEqual(serializer.validated_data, {"phone": "+33612345678"})
53+
self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber)
54+
55+
def test_region(self):
56+
class PhoneNumberSerializer(serializers.Serializer):
57+
phone = PhoneNumberField(region="FR")
58+
59+
serializer = PhoneNumberSerializer(data={"phone": "0612345678"})
60+
self.assertIs(serializer.is_valid(), True)
61+
self.assertEqual(serializer.validated_data, {"phone": "+33612345678"})
62+
self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber)
63+
64+
def test_region_invalid(self):
65+
class PhoneNumberSerializer(serializers.Serializer):
66+
phone = PhoneNumberField(region="GB")
67+
68+
serializer = PhoneNumberSerializer(data={"phone": "0612345678"})
69+
self.assertIs(serializer.is_valid(), False)
70+
self.assertEqual(serializer.validated_data, {})
71+
self.assertEqual(serializer.errors, {"phone": ["Enter a valid phone number."]})
72+
73+
@override_settings(PHONENUMBER_DEFAULT_REGION="FR")
74+
def test_region_from_settings(self):
75+
class PhoneNumberSerializer(serializers.Serializer):
76+
phone = PhoneNumberField()
77+
78+
serializer = PhoneNumberSerializer(data={"phone": "0612345678"})
79+
self.assertIs(serializer.is_valid(), True)
80+
self.assertEqual(serializer.validated_data, {"phone": "+33612345678"})
81+
self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber)
82+
83+
@override_settings(PHONENUMBER_DEFAULT_REGION="GB")
84+
def test_region_kwarg_precedes_setting(self):
85+
class PhoneNumberSerializer(serializers.Serializer):
86+
phone = PhoneNumberField(region="FR")
87+
88+
serializer = PhoneNumberSerializer(data={"phone": "0612345678"})
89+
self.assertIs(serializer.is_valid(), True)
90+
self.assertEqual(serializer.validated_data, {"phone": "+33612345678"})
91+
self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber)
92+
93+
def test_invalid_region(self):
94+
with self.assertRaisesMessage(
95+
ValueError, "“INVALID” is not a valid region code. Choices are"
96+
):
97+
98+
class PhoneNumberSerializer(serializers.Serializer):
99+
phone = PhoneNumberField(region="INVALID")

0 commit comments

Comments
 (0)