Django Rest Framework: Dynamically return subset of fields

后端 未结 8 705
南笙
南笙 2020-11-28 18:16

Problem

As recommended in the blogpost Best Practices for Designing a Pragmatic RESTful API, I would like to add a fields query parameter to a Django R

8条回答
  •  春和景丽
    2020-11-28 18:52

    serializers.py

    class DynamicFieldsSerializerMixin(object):
    
        def __init__(self, *args, **kwargs):
            # Don't pass the 'fields' arg up to the superclass
            fields = kwargs.pop('fields', None)
    
            # Instantiate the superclass normally
            super(DynamicFieldsSerializerMixin, self).__init__(*args, **kwargs)
    
            if fields is not None:
                # Drop any fields that are not specified in the `fields` argument.
                allowed = set(fields)
                existing = set(self.fields.keys())
                for field_name in existing - allowed:
                    self.fields.pop(field_name)
    
    
    class UserSerializer(DynamicFieldsSerializerMixin, serializers.HyperlinkedModelSerializer):
    
        password = serializers.CharField(
            style={'input_type': 'password'}, write_only=True
        )
    
        class Meta:
            model = User
            fields = ('id', 'username', 'password', 'email', 'first_name', 'last_name')
    
    
        def create(self, validated_data):
            user = User.objects.create(
                username=validated_data['username'],
                email=validated_data['email'],
                first_name=validated_data['first_name'],
                last_name=validated_data['last_name']
            )
    
            user.set_password(validated_data['password'])
            user.save()
    
            return user
    

    views.py

    class DynamicFieldsViewMixin(object):
    
     def get_serializer(self, *args, **kwargs):
    
        serializer_class = self.get_serializer_class()
    
        fields = None
        if self.request.method == 'GET':
            query_fields = self.request.QUERY_PARAMS.get("fields", None)
    
            if query_fields:
                fields = tuple(query_fields.split(','))
    
    
        kwargs['context'] = self.get_serializer_context()
        kwargs['fields'] = fields
    
        return serializer_class(*args, **kwargs)
    
    
    
    class UserList(DynamicFieldsViewMixin, ListCreateAPIView):
        queryset = User.objects.all()
        serializer_class = UserSerializer
    

提交回复
热议问题