Skip to content

Commit

Permalink
Implement region argument for serializerfields
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
francoisfreitag committed Aug 28, 2022
1 parent b746061 commit 1f012e4
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 3 deletions.
10 changes: 8 additions & 2 deletions phonenumber_field/serializerfields.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
from django.conf import settings
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from phonenumber_field.phonenumber import to_python
from phonenumber_field.phonenumber import to_python, validate_region


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

def __init__(self, *args, region=None, **kwargs):
super().__init__(*args, **kwargs)
validate_region(region)
self.region = region or getattr(settings, "PHONENUMBER_DEFAULT_REGION", None)

def to_internal_value(self, data):
str_value = super().to_internal_value(data)
phone_number = to_python(str_value)
phone_number = to_python(str_value, region=self.region)
if phone_number and not phone_number.is_valid():
raise ValidationError(self.error_messages["invalid"])
return phone_number
74 changes: 73 additions & 1 deletion tests/test_serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.test import SimpleTestCase
from django.test import SimpleTestCase, override_settings
from rest_framework import serializers

from phonenumber_field.phonenumber import PhoneNumber
from phonenumber_field.serializerfields import PhoneNumberField

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

s = PhoneNumberSerializer(data={"phone": 1})
self.assertIs(s.is_valid(), False)

def test_empty_required(self):
class PhoneNumberSerializer(serializers.Serializer):
phone = PhoneNumberField()

serializer = PhoneNumberSerializer(data={"phone": ""})
self.assertIs(serializer.is_valid(), False)
self.assertEqual(serializer.validated_data, {})

def test_empty_optional(self):
class PhoneNumberSerializer(serializers.Serializer):
phone = PhoneNumberField(allow_blank=True)

serializer = PhoneNumberSerializer(data={"phone": ""})
self.assertIs(serializer.is_valid(), True)
self.assertEqual(serializer.validated_data, {"phone": ""})

def test_e164_phone_number(self):
class PhoneNumberSerializer(serializers.Serializer):
phone = PhoneNumberField()

serializer = PhoneNumberSerializer(data={"phone": "+33612345678"})
self.assertIs(serializer.is_valid(), True)
self.assertEqual(serializer.validated_data, {"phone": "+33612345678"})
self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber)

def test_region(self):
class PhoneNumberSerializer(serializers.Serializer):
phone = PhoneNumberField(region="FR")

serializer = PhoneNumberSerializer(data={"phone": "0612345678"})
self.assertIs(serializer.is_valid(), True)
self.assertEqual(serializer.validated_data, {"phone": "+33612345678"})
self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber)

def test_region_invalid(self):
class PhoneNumberSerializer(serializers.Serializer):
phone = PhoneNumberField(region="GB")

serializer = PhoneNumberSerializer(data={"phone": "0612345678"})
self.assertIs(serializer.is_valid(), False)
self.assertEqual(serializer.validated_data, {})
self.assertEqual(serializer.errors, {"phone": ["Enter a valid phone number."]})

@override_settings(PHONENUMBER_DEFAULT_REGION="FR")
def test_region_from_settings(self):
class PhoneNumberSerializer(serializers.Serializer):
phone = PhoneNumberField()

serializer = PhoneNumberSerializer(data={"phone": "0612345678"})
self.assertIs(serializer.is_valid(), True)
self.assertEqual(serializer.validated_data, {"phone": "+33612345678"})
self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber)

@override_settings(PHONENUMBER_DEFAULT_REGION="GB")
def test_region_kwarg_precedes_setting(self):
class PhoneNumberSerializer(serializers.Serializer):
phone = PhoneNumberField(region="FR")

serializer = PhoneNumberSerializer(data={"phone": "0612345678"})
self.assertIs(serializer.is_valid(), True)
self.assertEqual(serializer.validated_data, {"phone": "+33612345678"})
self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber)

def test_invalid_region(self):
with self.assertRaisesMessage(
ValueError, "“INVALID” is not a valid region code. Choices are"
):

class PhoneNumberSerializer(serializers.Serializer):
phone = PhoneNumberField(region="INVALID")

0 comments on commit 1f012e4

Please sign in to comment.