【问题标题】:Dynamic serializer Django REST: "AttributeError: 'Serializer' object has no attribute 'pk'"动态序列化程序 Django REST:“AttributeError:‘Serializer’对象没有属性‘pk’”
【发布时间】:2021-08-06 17:13:23
【问题描述】:

我希望能够根据上下文或对象的属性动态更改我的序列化程序值。

为此,我做了一个序列化程序,可以根据给定的上下文信息在 __ init __ 中进行修改。但是我试图调用它来创建一个新用户,这通常可以工作,但是嵌套字段用户有问题......

这是我的代码:

class UsersSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'
        extra_kwargs = {'password': {'write_only': True}}


    user_permissions = serializers.SerializerMethodField('get_user_permissions')
    groups = serializers.SerializerMethodField('get_groups')


    def get_user_permissions(self, user):
        LOGGER.info(list(user.user_permissions.all().values_list('id', flat=True)))
        return list(user.user_permissions.all().values_list('id', flat=True))


    def get_groups(self, user):
        return list(user.groups.all().values_list('id', flat=True))


class UsersSerializerGeneralInfo(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'email', 'username']


class AccessSerializer(serializers.ModelSerializer):
    class Meta:
        model = Access
        fields = '__all__'


class SNHUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = SNHUser
        fields = '__all__'


    def __init__(self, *args, **kwargs):
        super().__init__(self, *args, **kwargs)
        # If raw, not getting any additional fields
        if not self.context.get("get_raw", False):
            # Retrieving access if given in context
            if self.context.get("get_accesses", False):
                self.fields['accesses'] = serializers.SerializerMethodField()
            # Retrieving all user information if given in context
            if not self.context.get("get_all_user_informations", False):
                self.fields['user'] = UsersSerializer()
            else:
                self.fields['user'] = UsersSerializerGeneralInfo()
            # Additional fields if not raw
            self.fields['implants'] = serializers.SerializerMethodField()
            self.fields['users_clinical_trials'] = serializers.SerializerMethodField()
            self.fields['implant_patients'] = serializers.SerializerMethodField()


    ## Save function
    def save(self, *args, **kwargs):
        self.full_clean()
        return super().save(*args, **kwargs)


    ## Validation method method used to validate field
    def clean(self):
        validate_password(self.user.password)


    def create(self, validated_data):
        # Create first the django user
        user_data = validated_data.pop('user')
        user = User.objects.create_user(**user_data)
        # Create the layer of profile for the user
        return SNHUser.objects.create(user=user, **validated_data)


    def to_representation(self, obj):
        return super(SNHUserSerializer, self).to_representation(obj)


    def get_accesses(self, obj):
        # If context parameter is given, adding accesses
        if self.context.get("get_accesses", False):
            accesses = Access.objects.filter(snh_user=obj.id)
            ser = AccessSerializer(accesses, many=True)
            return ser.data
        else:
            return None


    def get_implants(self, obj):
        # If patient, returning implants linked else None
        if obj.role == "Patient":
            from apps.provisioning.serializers import ImplantSerializer
            from apps.medicalmanagement.module.implant_patient import get_implants_by_patient
            implants_o = get_implants_by_patient(obj)
            if implants_o != []:
                ser = ImplantSerializer(implants_o, many=True)
                return ser.data
            else:
                return implants_o
        return None


    def get_users_clinical_trials(self, obj):
        from apps.medicalmanagement.models import UserClinicalTrial
        from apps.medicalmanagement.serializers import UserClinicalTrialSerializer
        from apps.medicalmanagement.module.user_clinical_trial import get_users_clinical_trials
        users_clinical_trials_o: UserClinicalTrial = get_users_clinical_trials(
            snh_user=obj
        )
        return UserClinicalTrialSerializer(users_clinical_trials_o, many=True).data


    def get_implant_patients(self, obj):
        # If patient, returning implants patients links else None
        if obj.role == "Patient":
            from apps.medicalmanagement.models import ImplantPatient
            from apps.medicalmanagement.serializers import ImplantPatientSerializer
            from apps.medicalmanagement.module.implant_patient import get_implant_patients
            implant_patient_o: ImplantPatient = get_implant_patients(patient=obj)
            return ImplantPatientSerializer(implant_patient_o, many=True).data
        else:
            return None

问题是:当我尝试实例化编写并创建一个新用户时,我收到此错误:

    if ser.is_valid():

  File "\lib\site-packages\rest_framework\serializers.py", line 220, in is_valid

    self._validated_data = self.run_validation(self.initial_data)

  File "\site-packages\rest_framework\serializers.py", line 421, in run_validation

    self.run_validators(value)

  File "\site-packages\rest_framework\serializers.py", line 454, in run_validators

    super().run_validators(to_validate)

  File "\site-packages\rest_framework\fields.py", line 591, in run_validators

    validator(value, self)

  File "\lib\site-packages\rest_framework\validators.py", line 151, in __call__

    queryset = self.exclude_current_instance(attrs, queryset, serializer.instance)

  File "\lib\site-packages\rest_framework\validators.py", line 144, in exclude_current_instance

    return queryset.exclude(pk=instance.pk)

AttributeError: 'SNHUserSerializer' object has no attribute 'pk'

我没有定义任何 pk 属性,所以我想它们是自动添加的。

这就是我如何调用我的序列化程序,只是传递数据而无需任何参数。

ser = SNHUserSerializer(data=data)
if ser.is_valid():

我之前做的是这个(而且效果很好,但初始化时无法更改):

class SNHUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = SNHUser
        fields = '__all__'


    user = UsersSerializer()


    def create(self, validated_data):
        # Create first the django user
        user_data = validated_data.pop('user')
        user = User.objects.create_user(**user_data)
        # Create the layer of profile for the user
        return SNHUser.objects.create(user=user, **validated_data)


    def to_representation(self, obj):
        return super(SNHUserSerializer, self).to_representation(obj)

您是否知道可能导致此问题的原因?

谢谢

【问题讨论】:

  • 你能分享一下你的看法吗
  • @bdbd 添加了信息,没什么特别的,就是一个普通的调用。这是导致问题的嵌套用户关系,但无法弄清楚确切的问题是什么......

标签: python python-3.x django django-rest-framework


【解决方案1】:

这个问题是由这一行引起的:

super().__init__(self, *args, **kwargs)

你需要删除self:

super().__init__(*args, **kwargs)

【讨论】:

    猜你喜欢
    • 2015-07-10
    • 2015-03-12
    • 2013-02-02
    • 2019-07-05
    • 1970-01-01
    • 1970-01-01
    • 2023-01-20
    • 2016-04-02
    • 2016-11-21
    相关资源
    最近更新 更多