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
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}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With