Home > Software engineering >  Null in response which should't exist Django
Null in response which should't exist Django

Time:07-17

When I send request in Postman like this: enter image description here

it returns me all fields fine expect the profile_photo. profile_photo in response is null and I don't know what is the problem. It should be the new uuid photo name.

Here is my model:

class User(AbstractBaseUser, PermissionsMixin):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    email = models.EmailField(_('email address'), unique=True)
    first_name = models.CharField(max_length=150, blank=True)
    last_name = models.CharField(max_length=150, blank=True)
    city = models.CharField(max_length=150, blank=True)
    description = models.CharField(max_length=1000, blank=True) 
    profile_photo = models.CharField(max_length=500, blank=True)
    date_joined = models.DateTimeField(default=timezone.now)
    about = models.TextField(_(
        'about'), max_length=500, blank=True)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    objects = CustomAccountManager()
    object = models.Manager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name', 'city']

    def __str__(self):
        return self.email

This is my view:

class CustomUserUpdate(generics.UpdateAPIView):
    permission_classes = [IsAuthenticated]
    queryset = User.objects.all()
    serializer_class = UserUpdateSerializer

    def get_object(self):
        return self.request.user

This is my serializer. Here i am setting the new photo name. When I print the new name here like this: print(instance.profile_photo) it shows me the new file name fine. But in the response i get null.

class UserUpdateSerializer(serializers.ModelSerializer):
    profile_photo = serializers.FileField(required=False)
    class Meta:
        model = User
        fields = ('email', 'first_name', 'last_name', 'city', 'description', 'profile_photo')

    def __init__(self, *args, **kwargs):
        super(UserUpdateSerializer, self).__init__(*args, **kwargs)
        self.fields['email'].required = False
        self.fields['description'].required = False

    def update(self, instance, validated_data):
        if instance.id == self.context['request'].user.id:
            instance.email = validated_data.get('email', instance.email)
            instance.first_name = validated_data.get('first_name', instance.first_name)
            instance.last_name = validated_data.get('last_name', instance.last_name)
            instance.city = validated_data.get('city', instance.city)
            instance.description = validated_data.get('description', instance.description)
            uploaded_file = validated_data.get('profile_photo', None)
            if uploaded_file:
                validate_extension(uploaded_file.name)
                instance.profile_photo = handle_uploaded_file(uploaded_file)
            instance.save()
        return instance

def handle_uploaded_file(file):
    extension = os.path.splitext(file.name)[1]
    new_filename = f"{uuid.uuid4()}{extension}"

    destination = open(f'static/user/images/{new_filename}', 'wb ')
    for chunk in file.chunks():
        destination.write(chunk)

    destination.close()
    return new_filename

def validate_extension(filename):
    extension = os.path.splitext(filename)[1].replace(".", "")
    if extension.lower() not in ALLOWED_IMAGE_EXTENSIONS:
        raise serializers.ValidationError(
            (f'Invalid uploaded file type: {filename}'),
            code='invalid',
        )

CodePudding user response:

While sending requests you are passing file as input to the serializer. Serializer validates it and saves it. Till here it is perfectly fine.

Now while returning the response it expects a file from instance.profile_photo but to the serializer validator's surprise, it contains a string value (i.e UUID file name). The problem is here!

We got the bug point. Let's solve it.

To solve it, differentiate the names for the request(File) and response (File name i.e UUID string):

class UserUpdateSerializer(serializers.ModelSerializer):
    profile_image = serializers.FileField(required=False, write_only=True)
    profile_photo = serializers.ReadOnlyField()
    class Meta:
        model = User
        fields = ('email', 'first_name', 'last_name', 'city', 'description', 'profile_photo', 'profile_image')

    def __init__(self, *args, **kwargs):
        super(UserUpdateSerializer, self).__init__(*args, **kwargs)
        self.fields['email'].required = False
        self.fields['description'].required = False

    def update(self, instance, validated_data):
        if instance.id == self.context['request'].user.id:
            instance.email = validated_data.get('email', instance.email)
            instance.first_name = validated_data.get('first_name', instance.first_name)
            instance.last_name = validated_data.get('last_name', instance.last_name)
            instance.city = validated_data.get('city', instance.city)
            instance.description = validated_data.get('description', instance.description)
            uploaded_file = validated_data.get('profile_image', None)
            if uploaded_file:
                validate_extension(uploaded_file.name)
                instance.profile_photo = handle_uploaded_file(uploaded_file)
            instance.save()
        return instance

We have solved the bug!

Cheers!

  • Related