简体   繁体   中英

Django rest framework serializer: required_fields

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 attribute in the model is not null=True or blank=True , the Serializer will set each field as required=True .

Otherwise, 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 (eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM