Django-rest-framework: extra_kwargs = {'field': {'required': True}} fails when model set (null=True blank=False, default=None)

Created on 5 Oct 2016  路  7Comments  路  Source: encode/django-rest-framework

Given a model

# models.py

class User(AbstractBaseUser):
    email = EmailField("email", null=True, blank=False, default=None)
    ...

and a ModelSerializer:

# serializers.py

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('username', 'password', 'email',)
        extra_kwargs = {'email': {'required': True}}

the extra kwarg {'email': {'required': True}} will be ignored.

The problem seems to be in rest_framework/fields.py

class Field(object):
     ...

    def validate_empty_values(self, data):
        """
        Validate empty values, and either:

        * Raise `ValidationError`, indicating invalid data.
        * Raise `SkipField`, indicating that the field should be ignored.
        * Return (True, data), indicating an empty value that should be
          returned without any further validation being applied.
        * Return (False, data), indicating a non-empty value, that should
          have validation applied as normal.
        """

        ## data is None

        if self.read_only:
            return (True, self.get_default())

        if data is empty:    ## THIS EVALUATES TO FALSE AND NEVER CHECK self.required.
            if getattr(self.root, 'partial', False):
                raise SkipField()
            if self.required:
                self.fail('required')
            return (True, self.get_default())

        if data is None:     ## MAY BE self.requeired SHOULD BE CHECKED HERE.
            if not self.allow_null:
                self.fail('null')
            return (True, None)

       return (False, data)

Most helpful comment

@tomchristie Thank you very much for the advice. The serializer works as I expected using

extra_kwargs = {'email': {'allow_null': False, 'required': True}}

Thanks!

All 7 comments

If data is None, your field has been provided and the required constraint is met.
I'm closing it on this basis.
Will consider reopening with a complete failing test case including how / what data is passed on to the serializer.

If data is None, your field has been provided and the required constraint is met.

@xordoquy Sorry, I don't get it. If data is None a required field should raise an exception.

The serializer email field is set to required (overwriting the default field model behavior with extra_kwargs). Then, the DRF form sends None (which is the only valid empty value for this field) and the validation never happens.

Nop, none may say that the field has been provided with a null value. This may indicate an intent which respects the required constraint. There may be other non trivial cases when dealing with forms as well. In all the cases we need something we can run out of the box and w茅re missing inputs here

@hacknaked Your model includes null=True, so the autogenerated serializer field is including allow_null=True. Either don't include allow_null on the model field, or include 'allow_null': False in the extra_kwargs.

Further docs on each of required, allow_blank and allow_null available here: http://www.django-rest-framework.org/api-guide/fields/

@tomchristie Thank you very much for the advice. The serializer works as I expected using

extra_kwargs = {'email': {'allow_null': False, 'required': True}}

Thanks!

@tomchristie Thank you very much for the advice. The serializer works as I expected using

extra_kwargs = {'email': {'allow_null': False, 'required': True}}

Thanks!

I am able to use it for single field for multiple fields I am not able to use it
i.e.,
if i give

extra_kwargs = {
'username': {'allow_null': True, 'required': False}
'email': {'allow_null': True, 'required': False}
}
i only get the required result for username

@hacknaked sometimes 'allow_null=False' isn't enough to make your field required. in this cases, add 'allow_blank=False' can solve the problem.

Was this page helpful?
0 / 5 - 0 ratings