Django Ошибка значения модели при вставке данных в модель - PullRequest
0 голосов
/ 18 апреля 2020

Я пытаюсь вставить данные формы в модели User и UserGroup, используя APIView.

class User(AbstractBaseUser, PermissionsMixin):

    email = models.EmailField(max_length=255, unique=True)
    first_name = models.CharField(max_length=255, blank=False, null=False)
    last_name = models.CharField(max_length=255, blank=False, null=False)
    profile_picture = models.ImageField(upload_to='profile_pictures/', max_length=None, null=True, blank=True)
    is_active = models.BooleanField(default=True)

    objects = UserManager()

    USERNAME_FIELD = 'email'


class UserGroup(models.Model):

    user = models.ForeignKey(User, related_name='user_id', on_delete=models.CASCADE, blank=False)
    role = models.ForeignKey(Role, related_name='role_id', on_delete=models.CASCADE, blank= False)

Я могу вставить данные в модель User но когда я пытаюсь сделать то же самое с моделью UserGroup, возвращается сообщение об ошибке.

ValueError: Cannot assign "17": "UserGroup.user" must be a "User" instance.

Я хочу, чтобы этот API создал пользователя и немедленно назначил роль вновь созданному пользователю, вставив role_id и user_id в модели UserGroup.

Я создал два разных сериализатора UserSerializer и UserGroup сериализатора, и у обоих есть свой собственный метод создания для pu sh экземпляра в модель. Кроме того, в полезной нагрузке после запроса я принимаю все поля модели User, но для модели UserGroup я просто принимаю поле role, а не поле user, поскольку его значение необходимо сгенерировать после создания пользователя. .

Мне также придется использовать транзакцию для отката, если пользователь создан, но API не удалось назначить роль этому пользователю. Итак, я хочу знать, является ли это подходящим способом для выполнения этой задачи. Класс UserAPIViews (APIView):

permission_classes = [IsAuthenticated]

parser_classes = (FormParser, MultiPartParser)

def post(self, request, format=None):

    user_group={} #dictionary for UserGroupSerializer

    user_group['role'] = request.data['user_group'] # adding Role object to UserGroup dictionary from request payload.

    del request.data['user_group'] # removing user_group (key,value) from the payload so that dictionary could used for UserSerializer

    user_serialized_data = serializers.UserSerializer(data=request.data) # Serializing request payload dictionary with the UserSerializer

    if user_serialized_data.is_valid(): # check the dictionary is validated or invalidated by the UserSerializer

        try:

            user_created_with_id = user_serialized_data.save() # if the dictionary is validated save the UserSerilaized instance to the User model.
            # if the reqest payload dictionary is saved successfully then the save() will return the id of newly created object.
        except IntegrityError as error:

            message = f'Email already exist.'

            return Response ({
                'error_message' : message,
                'status' : status.HTTP_226_IM_USED
            })

    else:
        return Response ({'user_serilization_error':user_serialized_data.error_messages}) # return Payload dictionary has been invalidated by the UserSerilaizer.
    # add the user parameter to the user_group dictionary. The value of key user should be the object id of newly created user.
    user_group['user'] = user_created_with_id
    # now the UserGroupSerilaizer dictionary is ready.
    # user_group ={"user":user_created_with_id, "role":<Role: Role object (2)>} 
    # serilaize the user_group dictionary with the UserGroupSerilaizer.
    # this is where it generates a ValueError stating that UserGroup.user must be a User instance.
    user_group_serialized_data = serializers.UserGroupSerializer(data=user_group)

    if user_group_serialized_data.is_valid():

        user_group_id = user_group_serialized_data.save()

        success_message = 'User has been created.'

        return Response({
            'success_message' : success_message,
            'status' : status.HTTP_201_CREATED
        })
    else:
        return Response ({'user_group_serilization_error':user_serialized_data.error_messages})

UserGroupSerializer

class UserGroupSerializer(serializers.Serializer):

    class Meta:
        model = UserGroup

    user = serializers.IntegerField(required=True)
    role = serializers.IntegerField(required=True)

    def create(self, validated_data):
        user_role_relation_id = UserGroup.objects.create(**validated_data)
        return user_role_relation_id

UserSerializer

class UserSerializer(serializers.Serializer):

    class Meta:
        model = User

    id = serializers.IntegerField(read_only=True)
    email = serializers.EmailField(required=True)
    first_name = serializers.CharField(max_length=255, required=True)
    last_name = serializers.CharField(max_length=255, required=True)
    profile_picture = serializers.ImageField(max_length=None, allow_empty_file=True, use_url= False, required=False)
    password = serializers.CharField(max_length = 255, write_only=True, required=True)

    def create(self, validated_data):

        user_id = User.objects.create_user(**validated_data)

        return user_id

Запрос API имеет полезная нагрузка, как указано ниже -

{
"first_name":"", # Serialized by UserSerializer
"last_name":"", # Serialized by UserSerializer
"email":"", # Serialized by UserSerializer
"password":"", # Serialized by UserSerializer
"profile_picture":"", # Serialized by UserSerializer
"user_role:":"" # Serialized by UserGroupSerializer
}

Мне пришлось разделить эту полезную нагрузку на два разных словаря, один для сериализации с помощью UserSerializer, а другой для сериализации с помощью UserGroupSerializer.

Пожалуйста, прочитайте комментарии класса APIView, чтобы понять поток.

Ответы [ 2 ]

0 голосов
/ 20 апреля 2020

Похоже, проблема в UserGroupSerializer

вы смотрели на это: https://www.django-rest-framework.org/api-guide/serializers/#dealing -with-nested-objects

(вы не должны были иметь настроить

   user_group['user']

извините за путаницу в комментарии)

0 голосов
/ 18 апреля 2020

ValueError: Невозможно назначить «17»: «UserGroup.user» должен быть экземпляром «User». эта ошибка говорит о том, что пользователь должен дать пользователю экземпляр ввода UserGroup.user = user_object

. Вы можете сделать это:

current_user = User.objects.get(id = 17)
UserGroup.user = current_user 

или

UserGroup.user = request.user
...