DRF:如何在使用深度选项的序列化程序中隐藏密码?

DRF: How to hide the password in serializers that use the depth option?

我正在为 User 模型使用以下序列化程序,但是当我使用深度处理外键时,密码显示在 User 对象中。

用户序列化器:

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        read_only_fields = ('is_active', 'is_staff', 'is_superuser',)
        exclude = ('password', )
        extra_kwargs = {'password': {'write_only': True, 'min_length': 4}}

在下面的序列化器中一切正常:

class AuditSerializer(serializers.ModelSerializer):
    def __init__(self, instance=None, **kwargs):
        if instance:
            setattr(self.Meta, 'depth', 10)
        else:
            setattr(self.Meta, 'depth', 0)
        super(AuditSerializer, self).__init__(instance, **kwargs)

    initiator = UserSerializer(read_only=True)

    class Meta:
        model = Audit
        fields = ['id', 'initiator']
        read_only_fields = ['id', 'initiator']
        depth = 0

但在下面与之前model/serializer有关的密码问题:

class AuditAttachmentSerializer(serializers.ModelSerializer):
    def __init__(self, instance=None, **kwargs):
        if instance:
            setattr(self.Meta, 'depth', 10)
        else:
            setattr(self.Meta, 'depth', 0)
        super(AuditAttachmentSerializer, self).__init__(instance, **kwargs)

    class Meta:
        model = AuditAttachment
        fields = ['id', 'audit']
        read_only_fields = ['id']
        depth = 0

我把__init__方法删掉改成了下面的解决方法

我在使用 depth 元属性时遇到了同样的问题。 password 被集成到序列化数据中。

第一个解)

根据@JPG 对原始 post 的评论,我使用了 to_representation() 方法,效果非常好!

我已经结束了与我的用户模型相关的序列化程序的这段代码:

from django.contrib.auth.models import Group
from rest_framework import serializers


class BaseGroupSerializer(serializers.ModelSerializer):

    class Meta:
        model = Group
        depth = 1
        fields = (
            'id',
            'name',
            'user_set',
        )
    
    def to_representation(self, instance):
        response = super().to_representation(instance)
        for user in response.get("user_set"):
            user.pop("password", None)
        return response

它只是弹出我组中每个用户的密码字段。

第二个解)

另一个简单的解决方案是直接引用 UserSerializer,您在其中明确排除了密码 exclude = ('password',)(或不包括它)。

在我的情况下,结果会是这样的:

from django.contrib.auth.models import Group
from rest_framework import serializers
from ..serializers.base_user_serializer import BaseUserSerializer


class BaseGroupSerializer(serializers.ModelSerializer):

    user_set = BaseUserSerializer(many=True)       # <------

    class Meta:
        model = Group
        depth = 1
        fields = (
            'id',
            'name',
            'user_set',
        )

BaseUserSerializer 保持原样:

from rest_framework import serializers
from ..models.base_user import User


class BaseUserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        depth = 1
        fields = (
            'id',
            'username',
            'email',
            'first_name',
            'last_name',
            'full_name',
            'full_identification',
            'is_active',
            'groups',
            # 'password' is omitted here
        )

两种方式都行。第二种方法的唯一问题是,在某些情况下,如果您还在 BaseUserSerializer.

中导入此 BaseGroupSerializer,您将面临循环导入

所以根据你的情况和你对进口的限制,...选择你的解决方案:)