即时更改序列化程序字段

wsw*_*wld 7 django serialization django-rest-framework

例如,我有以下序列化器:

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = (
            'userid',
            'password'
        )
Run Code Online (Sandbox Code Playgroud)

但我不想在GET上输出密码(当然我的真实例子还有其他字段).如果不编写其他序列化程序,我怎么能这样做?即时更改字段列表.有没有办法做到这一点?

Kev*_*own 21

您似乎正在寻找只写字段.因此,在创建时将需要该字段,但它根本不会显示给用户(与只读字段相反).幸运的是,Django REST Framework现在支持具有write_only属性的只写字段.

在Django REST Framework 3.0中,您只需要将额外的参数添加extra_kwargs元选项中.

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = (
            'userid',
            'password'
        )
        extra_kwargs = {
            'password': {
                'write_only': True,
            },
        }
Run Code Online (Sandbox Code Playgroud)

因为password应该进行哈希处理(你正在使用Django的用户,对吗?),你需要在密码进入时对其进行哈希处理.这应该在你的视图上完成,最有可能的方法是覆盖perform_createperform_update方法.

from django.contrib.auth.hashers import make_password

class UserViewSet(viewsets.ViewSet):

    def perform_create(self, serializer):
        password = make_password(self.request.data['password'])

        serializer.save(password=password)

    def perform_update(self, serializer):
        password = make_password(self.request.data['password'])

        serializer.save(password=password)
Run Code Online (Sandbox Code Playgroud)

在Django REST Framework 2.x中,您需要完全重新定义password序列化程序上的字段.

class UserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True)

    class Meta:
        model = User
        fields = (
            'userid',
            'password'
        )
Run Code Online (Sandbox Code Playgroud)

为了在Django REST Framework 2.x中提前散列密码,您需要覆盖pre_save.

from django.contrib.auth.hashers import make_password

class UserViewSet(viewsets.ViewSet):

    def pre_save(self, obj, created=False):
        obj.password = make_password(obj.password)

        super(UserViewSet, self).pre_save(obj, created=created)
Run Code Online (Sandbox Code Playgroud)

这将解决其他答案的常见问题,即用于创建/更新用户的相同序列化程序也将用于返回更新的用户对象作为响应.这意味着即使您只希望密码是只写的,密码仍会在响应中返回.此问题的另一个问题是密码可能会或可能不会在响应中进行哈希处理,这是您真正不想做的事情.