Skip to content

Commit 099c2d2

Browse files
committed
Fix lost region when PHONENUMBER_DEFAULT_FORMAT is NATIONAL
When `PHONENUMBER_DEFAULT_FORMAT` is set to `NATIONAL`, you used to get a validation error after setting a `PhoneNumberField` to a phone number that is not in the default region. This was because `PhoneNumberField` didn't override `to_python()`, so `CharField.to_python()` was called and returned `str(value)`. Since `str(value)` returns a string in the `NATIONAL` format, the region information was lost. I fixed this issue by overriding `to_python()` in `PhoneNumberField`, ensuring that a `PhoneNumber` is returned. This change forced me to move up the call to `super().get_prep_value()` because `CharField`'s implementation calls `self.to_python()`, which now returns a `PhoneNumber`. This allowed me to remove `if isinstance(value, PhoneNumber)` in `get_prep_value()` since `value` is now always a `PhoneNumber`.
1 parent 65bc14f commit 099c2d2

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

phonenumber_field/modelfields.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,16 @@ def _check_region(self):
8181
return [checks.Error(force_str(e), obj=self)]
8282
return []
8383

84+
def to_python(self, value):
85+
return to_python(value, region=self.region)
86+
8487
def get_prep_value(self, value):
8588
"""
8689
Perform preliminary non-db specific value checks and conversions.
8790
"""
88-
if not value:
89-
return super().get_prep_value(value)
90-
91-
if isinstance(value, PhoneNumber):
92-
parsed_value = value
93-
else:
94-
# Convert the string to a PhoneNumber object.
95-
parsed_value = to_python(value)
91+
parsed_value = super().get_prep_value(value)
92+
if not parsed_value:
93+
return parsed_value
9694

9795
if parsed_value.is_valid():
9896
# A valid phone number. Normalize it for storage.
@@ -103,7 +101,7 @@ def get_prep_value(self, value):
103101
# Not a valid phone number. Store the raw string.
104102
value = parsed_value.raw_input
105103

106-
return super().get_prep_value(value)
104+
return value
107105

108106
def from_db_value(self, value, expression, connection):
109107
return to_python(value)

tests/tests.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,23 @@ def test_save_field_to_database(self):
309309
transform=phone_transform,
310310
)
311311

312+
@override_settings(PHONENUMBER_DEFAULT_FORMAT="NATIONAL")
313+
def test_internal_phone_when_default_format_is_national(self):
314+
"""Test that the region is not lost in a string conversion."""
315+
tm = models.TestModel()
316+
tm.phone = "+41 52 424 2424"
317+
tm.full_clean()
318+
tm.save()
319+
pk = tm.id
320+
321+
tm = models.TestModel.objects.get(pk=pk)
322+
self.assertIsInstance(tm.phone, PhoneNumber)
323+
self.assertQuerySetEqual(
324+
models.TestModel.objects.all(),
325+
[(tm.pk, "", "+41524242424")],
326+
transform=phone_transform,
327+
)
328+
312329
def test_create_with_invalid_number_works(self):
313330
obj = models.TestModel.objects.create(phone="invalid")
314331
self.assertEqual(obj.phone.raw_input, "invalid")

0 commit comments

Comments
 (0)