DRF:在 ** 之后创建参数时嵌套序列化程序错误必须是映射,而不是 str
DRF: nested Serializer error on create argument after ** must be a mapping, not str
我有一个通过外键连接学校模型和用户模型的模型,如果正在创建学生,我希望将用户外键设置为实例,并将学校设置为由它的 id 选择但是我无法解决这个错误
TypeError at /api/users/student_register/
django.db.models.manager.BaseManager._get_queryset_methods.<locals>.create_method.<locals>.manager_method() argument after ** must be a mapping, not str
class User(AbstractBaseUser, PermissionsMixin):
....
email = models.EmailField(
is_superuser = models.BooleanField(default=False)
last_login = models.DateTimeField(
_("last login"), auto_now=True, auto_now_add=False)
class School(models.Model):
PROVINCE = (
...
)
SCHOOLTYPE = (
....
)
name = models.CharField(_("Name"), max_length=150, blank=False, null=True)
abbr = models.CharField(
_("Abbrivation"), max_length=10, blank=False, null=True)
zone = models.CharField(
_("Zone"), max_length=50, choices=PROVINCE)
Schooltype = models.CharField(
_("School type"), max_length=50, choices=SCHOOLTYPE)
schoolemail = models.EmailField(
_("School email"), max_length=254, blank=False, null=True) editable=False)
def __str__(self):
return self.name
这个应用模型将用户模型和学生模型连接在一起,这也是我通过嵌套序列化程序创建用户的模型
class Applied(models.Model):
class TYPES(models.TextChoices):
STUDENT = "STUDENT", "Student"
WORKER = "WORKER", "Worker"
type = models.CharField(_("type"), choices=TYPES.choices,
max_length=150, blank=False, null=True)
user = models.ForeignKey(User, verbose_name=_(
"useris"), related_name='useris', on_delete=models.PROTECT, blank=True, null=True)
school = models.ForeignKey(School, verbose_name=_(
'school'), related_name="applied", on_delete=models.CASCADE, blank=True, null=True)
serializers.py
class StudentSchoolSerializer(serializers.ModelSerializer):
user = serializers.CharField()
school = serializers.CharField()
type = serializers.HiddenField(
default=Applied.TYPES.STUDENT
)
class Meta:
model = Applied
fields = ['school', 'type', 'user']
# register a student
class RegisterSerializerStudent(serializers.ModelSerializer):
applied = StudentSchoolSerializer(required=True)
password = serializers.CharField(
write_only=True, required=True, validators=[validate_password])
firstname = serializers.CharField(required=True)
middlename = serializers.CharField(required=True)
lastname = serializers.CharField(required=True)
class Meta:
model = User
fields = ('firstname', 'middlename', 'sex', 'grade', 'image', 'room', 'type', 'lastname', 'age', 'password',
'phone', 'applied')
extra_kwargs = {'password': {'write_only': True},
'firstname': {'required': True},
'middelname': {'required': True},
'lastname': {'required': True},
'age': {'min_value': 1, 'max_value': 100}
}
def create(self, validated_data):
def create_new_id_number():
S = 10
not_unique = True
while not_unique:
unique_id = ''.join(random.choices(
string.ascii_uppercase + string.digits, k=S))
if not User.objects.filter(student_id=unique_id):
not_unique = False
return unique_id
applied = validated_data.pop('applied')
user = User.objects.create(
student_id=create_new_id_number(),
firstname=validated_data['firstname'],
middlename=validated_data['middlename'],
lastname=validated_data['lastname'],
age=validated_data['age'],
phone=validated_data['phone'],
image=validated_data['image'],
room=validated_data['room'],
sex=validated_data['sex'],
is_active='True',
type=User.TYPES.STUDENT,
)
user.set_password(validated_data['password'])
user.save()
for applies in applied:
Applied.objects.create(**applies, user=user)
return user
create 方法抛出错误,创建一个 User 实例而不是 Applied 实例
applied = validated_data.pop('applied')
在您的序列化程序中包含“applied”的值。您没有使用 many=true
选项调用 StudentSchoolSerializer。所以当你这样做时
for applies in applied:
Applied.objects.create(**applies, user=user)
applies
实际上是一个 str,而不是一个 dict。所以你不能使用 **.
如果只发送一个“applied”,可以直接保存
Applied.objects.create(**applied, user=user)
我有一个通过外键连接学校模型和用户模型的模型,如果正在创建学生,我希望将用户外键设置为实例,并将学校设置为由它的 id 选择但是我无法解决这个错误
TypeError at /api/users/student_register/
django.db.models.manager.BaseManager._get_queryset_methods.<locals>.create_method.<locals>.manager_method() argument after ** must be a mapping, not str
class User(AbstractBaseUser, PermissionsMixin):
....
email = models.EmailField(
is_superuser = models.BooleanField(default=False)
last_login = models.DateTimeField(
_("last login"), auto_now=True, auto_now_add=False)
class School(models.Model):
PROVINCE = (
...
)
SCHOOLTYPE = (
....
)
name = models.CharField(_("Name"), max_length=150, blank=False, null=True)
abbr = models.CharField(
_("Abbrivation"), max_length=10, blank=False, null=True)
zone = models.CharField(
_("Zone"), max_length=50, choices=PROVINCE)
Schooltype = models.CharField(
_("School type"), max_length=50, choices=SCHOOLTYPE)
schoolemail = models.EmailField(
_("School email"), max_length=254, blank=False, null=True) editable=False)
def __str__(self):
return self.name
这个应用模型将用户模型和学生模型连接在一起,这也是我通过嵌套序列化程序创建用户的模型
class Applied(models.Model):
class TYPES(models.TextChoices):
STUDENT = "STUDENT", "Student"
WORKER = "WORKER", "Worker"
type = models.CharField(_("type"), choices=TYPES.choices,
max_length=150, blank=False, null=True)
user = models.ForeignKey(User, verbose_name=_(
"useris"), related_name='useris', on_delete=models.PROTECT, blank=True, null=True)
school = models.ForeignKey(School, verbose_name=_(
'school'), related_name="applied", on_delete=models.CASCADE, blank=True, null=True)
serializers.py
class StudentSchoolSerializer(serializers.ModelSerializer):
user = serializers.CharField()
school = serializers.CharField()
type = serializers.HiddenField(
default=Applied.TYPES.STUDENT
)
class Meta:
model = Applied
fields = ['school', 'type', 'user']
# register a student
class RegisterSerializerStudent(serializers.ModelSerializer):
applied = StudentSchoolSerializer(required=True)
password = serializers.CharField(
write_only=True, required=True, validators=[validate_password])
firstname = serializers.CharField(required=True)
middlename = serializers.CharField(required=True)
lastname = serializers.CharField(required=True)
class Meta:
model = User
fields = ('firstname', 'middlename', 'sex', 'grade', 'image', 'room', 'type', 'lastname', 'age', 'password',
'phone', 'applied')
extra_kwargs = {'password': {'write_only': True},
'firstname': {'required': True},
'middelname': {'required': True},
'lastname': {'required': True},
'age': {'min_value': 1, 'max_value': 100}
}
def create(self, validated_data):
def create_new_id_number():
S = 10
not_unique = True
while not_unique:
unique_id = ''.join(random.choices(
string.ascii_uppercase + string.digits, k=S))
if not User.objects.filter(student_id=unique_id):
not_unique = False
return unique_id
applied = validated_data.pop('applied')
user = User.objects.create(
student_id=create_new_id_number(),
firstname=validated_data['firstname'],
middlename=validated_data['middlename'],
lastname=validated_data['lastname'],
age=validated_data['age'],
phone=validated_data['phone'],
image=validated_data['image'],
room=validated_data['room'],
sex=validated_data['sex'],
is_active='True',
type=User.TYPES.STUDENT,
)
user.set_password(validated_data['password'])
user.save()
for applies in applied:
Applied.objects.create(**applies, user=user)
return user
create 方法抛出错误,创建一个 User 实例而不是 Applied 实例
applied = validated_data.pop('applied')
在您的序列化程序中包含“applied”的值。您没有使用 many=true
选项调用 StudentSchoolSerializer。所以当你这样做时
for applies in applied:
Applied.objects.create(**applies, user=user)
applies
实际上是一个 str,而不是一个 dict。所以你不能使用 **.
如果只发送一个“applied”,可以直接保存
Applied.objects.create(**applied, user=user)