Order of Serializer Validation in Django REST Framework

后端 未结 4 439
天涯浪人
天涯浪人 2020-11-28 02:59

Situation

While working with validation in the Django REST Framework\'s ModelSerializer, I have noticed that the Meta.model

4条回答
  •  难免孤独
    2020-11-28 03:22

    I don't believe the above solutions work any more. In my case, my model has fields 'first_name' and 'last_name', but the API will only receive 'name'.

    Setting 'extra_kwargs' and 'validators' in the Meta class seems to have no effect, first_name and last_name are allways deemed required, and validators are always called. I can't overload the first_name/last_name character fields with

    anotherrepfor_first_name = serializers.CharField(source=first_name, required=False)
    

    as the names make sense. After many hours of frustration, I found the only way I could override the validators with a ModelSerializer instance was to override the class initializer as follows (forgive the incorrect indentation):

    class ContactSerializer(serializers.ModelSerializer):
    name = serializers.CharField(required=True)
    
    class Meta:
        model = Contact
        fields = [ 'name', 'first_name', 'last_name', 'email', 'phone', 'question' ]
    
    def __init__(self, *args, **kwargs):
        self.fields['first_name'] = serializers.CharField(required=False, allow_null=True, allow_blank=True)
        self.fields['last_name'] = serializers.CharField(required=False, allow_null=True, allow_blank=True)
        return super(ContactSerializer, self).__init__(*args, **kwargs)
    
    def create(self, validated_data):
        return Contact.objects.create()
    
    def validate(self, data):
        """
        Remove name after getting first_name, last_name
        """
        missing = []
        for k in ['name', 'email', 'question']:
            if k not in self.fields:
                missing.append(k)
        if len(missing):
            raise serializers.ValidationError("Ooops! The following fields are required: %s" % ','.join(missing))
        from nameparser import HumanName
        names = HumanName(data['name'])
        names.capitalize()
        data['last_name'] = names.last
        if re.search(r'\w+', names.middle):
            data['first_name'] = ' '.join([names.first, names.middle]) 
        else:
            data['first_name'] = names.first
        del(data['name'])
    
        return data
    

    Now the doc says that allowing blank and null with character fields is a no no, but this is a serializer, not a model, and as the API gets called by all kinds of cowboys, I need to cover my bases.

提交回复
热议问题