1

Using Django 2.0, Python 3.7, and the django-phonenumber-field (v 4.0.0) module. I have a model with my phone number field, that I don't want to be required ...

from phonenumber_field.modelfields import PhoneNumberField
...
class Coop(models.Model):
    name = models.CharField(max_length=250, null=False)
    type = models.ForeignKey(CoopType, on_delete=None)
    address = AddressField(on_delete=models.CASCADE)
    enabled = models.BooleanField(default=True, null=False)
    phone = PhoneNumberField(null=True)
    email = models.EmailField(null=True)
    web_site = models.TextField()

I have created this web/maps/views.py file to handle the POST request ...

class CoopDetail(APIView):
    """
    Retrieve, update or delete a coop instance.
    """
    def get_object(self, pk):
        try:
            return Coop.objects.get(pk=pk)
        except Coop.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        coop = self.get_object(pk)
        serializer = CoopSerializer(coop)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        coop = self.get_object(pk)
        serializer = CoopSerializer(coop, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

and then I have this web/maps/serializers.py call ...

class CoopSerializer(serializers.ModelSerializer):
    type = CoopTypeField()
    address = AddressTypeField()

    class Meta:
        model = Coop
        fields = ['id', 'name', 'type', 'address', 'enabled', 'phone', 'email', 'web_site']

    def to_representation(self, instance):
        rep = super().to_representation(instance)
        rep['type'] = CoopTypeSerializer(instance.type).data
        rep['address'] = AddressSerializer(instance.address).data
        return rep

    def create(self, validated_data):
        """
        Create and return a new `Snippet` instance, given the validated data.
        """
        return Coop.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """
        Update and return an existing `Coop` instance, given the validated data.
        """
        instance.name = validated_data.get('name', instance.name)
        instance.type = validated_data.get('type', instance.type)
        instance.address = validated_data.get('address', instance.address)
        instance.enabled = validated_data.get('enabled', instance.enabled)
        instance.phone = validated_data.get('phone', instance.phone)
        instance.email = validated_data.get('email', instance.email)
        instance.web_site = validated_data.get('web_site', instance.web_site)
        instance.save()
        return instance

But despite the fact I have specified I don't want a required phone number field, I'm getitng an error complaining about phone numbers can't be blank when I submit a curl request to the endpoint. When I submit this JSON

{
        "name": "1999",
        "type": {
            "name": "Coworking Space"
        },
        "address": {
            "street_number": "222",
            "route": "1212",
            "raw": "222 W. Merchandise Mart Plaza, Suite 1212",
            "formatted": "222 W. Merchandise Mart Plaza, Suite 1212",
            "latitude": 41.88802611,
            "longitude": -87.63612199,
            "locality": {
                "name": "Chicago",
                "postal_code": "60654",
                "state": 1
            }
        },
        "enabled": true,
        "phone": "",
        "email": null,
        "web_site": "http://www.1871.com/"
}

I get this error ...

{"phone":["This field may not be blank."]}
Dave
  • 15,639
  • 133
  • 442
  • 830

3 Answers3

0

What about extra_kwargs?

class CoopSerializer(serializers.ModelSerializer):
    class Meta:
        model = Coop
        fields = ['id', 'name', 'type', 'address', 'enabled', 'phone', 'email', 'web_site']
        extra_kwargs = {
            'phone': {
                'required': False, 
                'allow_blank': True
            }
        }
weAreStarsDust
  • 2,634
  • 3
  • 10
  • 22
0

You can add kwargs to a model serializer field like so:

class CoopSerializer(serializers.ModelSerializer):
    phone = serializers.CharField(
    required=False, # the phone key can be omitted from the request
    allow_blank=True, # the value can be an empty string
    allow_null=False # the value can be null/None
    )

jurms22
  • 101
  • 1
  • 3
0

In your model, add blank=True to the phone field if you want phone is blank when a user submits a form.

    phone = PhoneNumberField(null=True, blank=True)

Then, apply makemigrations and migrate to test your code. You don't need to specify this in the serializer if you have defined blank=True in model's field.

null=True means this field can be null in the database level. blank=True means this field can be blank in a form. Check this answer for more details.

Jun Zhou
  • 1,077
  • 1
  • 6
  • 19