【发布时间】: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