DRF: ошибка вложенного сериализатора при создании аргумента после ** должен быть отображением, а не строкой

У меня есть модель, которая связывает модель школы и модель пользователя через внешний ключ, и при создании ученика я хочу, чтобы внешний ключ пользователя был установлен как экземпляр, а также чтобы школа была выбрана по ее 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" в вашем сериализаторе. Вы не вызвали StudentSchoolSerializer с опцией many=true. Поэтому, когда вы делаете

for applies in applied:
    Applied.objects.create(**applies, user=user)

applies на самом деле является строкой, а не диктой. Поэтому вы не можете использовать **.

Если вы отправляете только одну "заявку", вы можете сохранить ее напрямую Applied.objects.create(**applied, user=user)

Вернуться на верх