helado
helado

Reputation: 895

Setting all serializer fields to be required

I have the next serializers:

class AddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = Address

class ClientSerializer(serializers.ModelSerializer):
  address = AddressSerializer()
  class Meta:
    model = Client
    fields = ('id', 'email', 'address')

The models:

class Address(models.Model):
    street = models.CharField(max_length=50, default='')
    zip = models.CharField(max_length=5, default='')
    state = models.CharField(max_length=50, choices=STATES ,default='')
    suburb = models.CharField(max_length=50, default='')
    num = models.CharField(max_length=7, blank=True, default='')
    country = models.CharField(max_length=50, default='')
    ref = models.CharField(max_length=120, blank=True)

class Client(models.Model):
    address = models.OneToOneField(Address, null=True)
    email = models.EmailField(unique=True, default='')

The expected behaviour is to have all the AddressSerializer fields as required, but that's not the case

When I check the options in the Client list api view I get the address as this:

"address": {
    "type": "field",
    "required": true,
    "read_only": false,
    "label": "Address"
}

But then when I check the Address list api view all my fields are optional:

"street": {
    "type": "string",
    "required": false,
    "read_only": false,
    "label": "Street",
    "max_length": 50
},
"state": {
    "type": "string",
    "required": false,
    "read_only": false,
    "label": "State",
    "max_length": 50
},
"zip": {
    "type": "string",
    "required": false,
    "read_only": false,
    "label": "ZIP",
    "max_length": 5
},

Why the fields that are supposed to be required are not?

How can I set all fields to be required preferably without using the extra_kwargs argument?

Upvotes: 2

Views: 3286

Answers (4)

Snow
Snow

Reputation: 3

If you need to do it on certain fields this worked for me:

some_field = serializers.PrimaryKeyRelatedField(
    queryset=YourModel.objects.all(),
    allow_null=False,
    allow_empty=False,
    required=True
)

def validate_some_field(self, value):
    if value is None:
        raise serializers.ValidationError("Required.")
    return value

Upvotes: 0

Maik Hoepfel
Maik Hoepfel

Reputation: 1797

There's another approach that might be considered cleaner than overriding get_fields:

I solved a similar problem (marking optional fields as required) by supplying extra_kwargs. Alternatively, if you want something more dynamic, you can override the get_extra_kwargs method on your serializer.

Upvotes: 0

zymud
zymud

Reputation: 2249

Field with default value is not required. You need to mark them as required explicitly:

class AddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = Address

    def get_fields(self):
        fields = super(AddressSerializer, self).get_fields()
        for field in fields.values():
            field.required = True
        return fields

Upvotes: 2

tamakisquare
tamakisquare

Reputation: 17077

if model_field.has_default() or model_field.blank or model_field.null:
    kwargs['required'] = False

The above is an excerpt from the DRF 3.1.2 source showing how the required attribute of auto-generated serializer field of ModelSerializer is determined.

What you have observed is by design. If you want an auto-generated serializer field to have required = True attribute, its corresponding model field must neither have a default value nor accept blank nor accept null.

Upvotes: 3

Related Questions