Я пытаюсь вставить данные формы в модели 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, чтобы понять поток.