Reputation: 798
Is it possible to set required fields as a list inside serializer? I don't want to override each fields with their type in the each line like this:
name = serializers.CharField(required=True)
description = serializers.CharField(required=True)
date_start = serializers.DateTimeField(required=True)
date_end = serializers.DateTimeField(required=True)
I just want to enumerate the names of fields
class CampaignStepFirstSerializer(serializers.ModelSerializer):
class Meta:
model = Campaign
fields = (
'name',
'description',
'date_start',
'date_end',
)
required_fields = fields
Upvotes: 2
Views: 3411
Reputation: 304
If the model field was instantiated with null=True
or blank=True
, or if the model field has a default value, the Serializer will automatically set the corresponding field as required=False
. (See the source of rest_framework.utils.field_mapping.get_field_kwargs
).
If you need to override this behavior, you can do this:
class CampaignStepFirstSerializer(serializers.ModelSerializer):
class Meta:
model = Campaign
fields = (
'name',
'description',
'date_start',
'date_end',
)
# 1st option. If some fields are required
extra_kwargs = {
'name': {'required': True},
'description': {'required': True},
'date_start': {'required': True},
'date_end': {'required': True},
}
# 2nd option. If all the fields are required:
extra_kwargs = {i:{'required': True} for i in fields}
Upvotes: 6
Reputation: 42007
There is no such option in DRF. The closest you can get with Meta
is extra_kwargs
(assuming you're using serializers.ModelSerializer
), with mentioning the field names separately with values being a dict with {'required': True}
. But that would be more work than explicitly mentioning required=True
while initializing the fields.
You can get what you want with a tiny bit of extension to the get_fields
method of serializers.Serializers
and any sublclass (e.g. serializers.ModelSerializer
):
class CampaignStepFirstSerializer(serializers.ModelSerializer):
def get_fields(self):
fields = super().get_fields()
try:
required_fields = self.Meta.required_fields
except AttributeError:
return fields
if not isinstance(required_fields, (list, tuple)):
raise TypeError(
'The value of `Meta.required_fields` option must be a list or tuple.'
)
for field_name in required_fields:
try:
field = fields[field_name]
except KeyError:
continue
if (
not field.read_only and
field.default is serializers.empty
):
field.required = True
fields[field_name] = field
return fields
class Meta:
model = Campaign
fields = (
'name',
'description',
'date_start',
'date_end',
)
required_fields = fields
As shown, in the Meta
class of the serializer class, you can define the required_fields
option and those fields will be made as required
if they are not read_only
and doesn't have a default.
One caveat of this is that, if you have some field defined explicitly on serializer with required=False
, and also mentioned the field in Meta.required_fields
, the __repr__
will show the required=False
(for example, when you'll be checking <serializer_instance>.fields
). serializers.Field.__repr__
is defined such that the initial arguments used in the creation of a field are shown as-is. The constructor (Field.__new__
) keeps a _kwargs
attribute to preserve the initial arguments.
This applies to all the explicitly declared fields (the metaclass serializers.SerailizerMetaclass
sets _declared_fields
attribute on the serializer class) so using read_only_fields
/write_only_fields
/extra_kwargs
Meta
options also don't impact the representation.
If you want, you can override the __repr__
of the field to change this but I don't think you should do so as that will break consistency with the rest of the design.
Upvotes: 1