Jeet Patel
Jeet Patel

Reputation: 1241

Django Model's Value Error while inserting data into model

I am trying to insert form-data into models User and UserGroup using 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)

I am able to insert data into model User but when I try to do the same with the model UserGroup it returns an error.

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

I want this API to create a user and assign a role immediately to the newly created user by inserting role_id and user_id in model UserGroup.

I have created two different serializer UserSerializer and UserGroup serializer and both has its own create method to push an instance into model. Also, in post request payload I am accepting all the fields of User model but for UserGroup model I am just accepting role field and not the user field as its value needs to be generated once the user is created.

I will have to use transaction as well to roll back if in case a user is created but the API has failed to assign the role to that user. So, I want to know is this an appropriate way to accomplish this task. class 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 request has the payload as stated below -

{
"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
}

I had to split this payload into two different dictionaries, one to be serialized by UserSerializer and another to be serialized by UserGroupSerializer.

Please read the comments of APIView class to understand the flow.

Upvotes: 0

Views: 374

Answers (2)

bb4L
bb4L

Reputation: 919

The issue seems to be in the UserGroupSerializer

have you looked at this: https://www.django-rest-framework.org/api-guide/serializers/#dealing-with-nested-objects

(you shouldn't have to adjust the

   user_group['user']

sorry for the confusion in the comment)

Upvotes: 0

Lavanya V
Lavanya V

Reputation: 357

ValueError: Cannot assign "17": "UserGroup.user" must be a "User" instance. this error says that have to give a user instanceas input UserGroup.user = user_object

you can do that by :

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

or

UserGroup.user = request.user

Upvotes: 1

Related Questions