stefanfoulis / django-phonenumber-field

A django model and form field for normalised phone numbers using python-phonenumbers
MIT License
1.49k stars 315 forks source link

Form field does not auto-detect region from international number #566

Closed alfonsrv closed 1 year ago

alfonsrv commented 1 year ago

In reference to what is likely the same issue to https://github.com/stefanfoulis/django-phonenumber-field/issues/99

International numbers cannot be submitted via the native form field. Using the code below and rendering the form errors out when attempting to submit an international number (e.g. +1 555 123 456) that is not within the configured default region. The form field errors out with:

Enter a valid phone number (e.g. 030 123456) or a number with an international call prefix.

Reading the error message on the frontend, one would assume that submitting an E.164-compliant number would have the field auto-resolve the most likely region, however this does not seem to be the case. The documentation also seems to suggest it should work that way (When no region is specified, an international example phone number in the E.164 format is suggested).

PHONENUMBER_DEFAULT_REGION = 'DE'

class Foo(models.Model):
    phone = PhoneNumberField()

class FooForm(forms.ModelForm):
    class Meta:
        model = Foo
        fields = ['phone']

This error is likely due to RegionalPhoneNumberWidget being the native form widget available and meant to be used in conjunction with PhoneNumberPrefixWidget when using international numbers.

Having a InternationalPhoneNumberWidget would be desirable that fits the functionality into the same field and auto-magically resolves the region based on the E.164 prefix.

francoisfreitag commented 1 year ago

an E.164-compliant number would have the field auto-resolve the most likely region

That’s indeed the expected behavior. I suspect there’s more at play, because I cannot reproduce the issue.

The following test passes: https://github.com/stefanfoulis/django-phonenumber-field/blob/60b5886eb45542dfba3de496225a8d3d37525e59/tests/tests.py#L447-L450

Besides, the following test also passes:

    @override_settings(PHONENUMBER_DEFAULT_REGION="FR")
    def test_modelfield_without_region_accepts_international_input(self):
        class MandatoryPhoneForm(forms.ModelForm):
            class Meta:
                model = models.MandatoryPhoneNumber
                fields = ["phone_number"]

        american_number = "+16044011234"
        form = MandatoryPhoneForm({"phone_number": american_number})
        self.assertIs(form.is_valid(), True)
        self.assertEqual(form.cleaned_data["phone_number"], american_number)
        form.save()
        instance = models.MandatoryPhoneNumber.objects.get()
        self.assertEqual(instance.phone_number, american_number)
alfonsrv commented 1 year ago

Ah, works. I have simply used a random number adding the country code (e.g. +1), assuming it would work but it seems like there indeed is some further validation at play here. Sorry for the trouble.