DRF: Allow all fields in GET request but restrict POST to just one field

后端 未结 1 693
暖寄归人
暖寄归人 2021-02-10 14:41

Let\'s understand it by example.

Say, I want to create FileUploader API, where it will be storing fields like id, file_path, file_name, size, owner, etc in database. See

1条回答
  •  伪装坚强ぢ
    2021-02-10 15:10

    IMHO, multiple serializers are only going to create more and more confusion.

    @AaronLelevier - I looked into other stackoverflow solution as you suggested. But finally decided to implement my own clean solution.

    I would prefer below solution:

    • Don't change your viewset (leave it default)
    • Add .validate() method in your serializer; along with other required .create or .update() etc. Here, real logic will go in validate() method. Where based on request type we will be creating validated_data dict as required by our serializer.

    I think this is the cleanest approach.

    Sample code: (modified serializer.py, views.py remain unchanged)

    class LayerFileSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = LayerFile
            fields = ('id', 'file','name','version','upload_date', 'size', 'maps')
            read_only_fields = ('name','version','owner','upload_date', 'size', 'maps')
    
        def validate(self, validated_data):
            if self.context['request'].method == 'PATCH':
                # catch here: validated_data only contains filed that are valid for serializer
                # for post/update/patch method only valid field is the file
                # but we need 'name' field as well so trick is to get name from the self.context[request].data
                validated_data['name'] = self.context['request'].data.get('name', None)
                if validated_data['name'] is None or validated_data['name'] == '':
                    raise serializers.ValidationError("'name' field cannot be empty!")
                return validated_data
            validated_data['owner'] = self.context['request'].user
            validated_data['name'] = os.path.splitext(validated_data['file'].name)[0]
            validated_data['size'] = validated_data['file'].size
            #print self.context['request'].overwrite
            log.debug("serialized layer data: %s" %validated_data)
    
            try:
                layer_obj = LayerFile.objects.get(owner=validated_data['owner'], name=validated_data['name'])
            except LayerFile.DoesNotExist:
                layer_obj = None
    
            if layer_obj:
                    raise serializers.ValidationError('Layer with same name already exist. Use overwrite flag to overwrite it.')
    
            return validated_data
    
        # This will handle rename
        def partial_update(self, instance, validated_data):
            instance.name = validated_data['name']
            return instance
    
        # this will handle POST - or layer upload
        def create(self, validated_data):
            return LayerFile.objects.create(**validated_data)
    

    0 讨论(0)
提交回复
热议问题