Django FileField/ImageField validation when the file upload is being done from the client side

339 Views Asked by At

When ever client wants to upload a file it first request the Django server for a pre-signed URL the server then generates a pre-signed URL and sends it back to the client.

The client can use this URL to upload to file directly to S3. Once the upload is successful the client sends the file key back to the server (the file key is also present in the response given by the server along with the URL).

Now I'm confused as to how to pass the FileField validation given that I only have the file key with me and not the actual file. For example:

class Company(models.Model):
    name = models.CharField(max_length=100)
    logo = models.ImageField(null=True)

    def __str__(self):
        return f'name:{self.name}'


class CompanySerializer(serializers.ModelSerializer):
    CLIENT_COMPANY_LOGO_KEY = 'logo'

    def to_internal_value(self, data):

        # Replace file/image keys with file/image instances so that they can pass validation.
        if data.get(self.CLIENT_COMPANY_LOGO_KEY):
            try:
                data[self.CLIENT_COMPANY_LOGO_KEY] = default_storage.open(data[self.CLIENT_COMPANY_LOGO_KEY])
            except (TypeError, OSError, ParamValidationError):
                pass

        return super().to_internal_value(data)

    def process_logo(self, validated_data):
        logo = validated_data.get(self.CLIENT_COMPANY_LOGO_KEY)
        if logo:
            # Replace file/image instances with keys.
            validated_data[self.CLIENT_COMPANY_LOGO_KEY] = logo.name

        return validated_data

    def create(self, validated_data):

        validated_data = self.process_logo(validated_data)

        company = super().create(validated_data)

        return company

Within the serializer I'm first replacing the file key with the actual file using the default_storage which is hooked up to S3 using django-storages. Then once the file has been successfully validated, I then again replace the actual file with the file key in the process_logo function.

The reason I replace the actual file with the file is because it is slowing down the create method (upto 30s).

I feel like this is a very hacky method and wanted to know if there is a better way to handle this situation. Should I replace the FileField/ImageField with a CharField and not do any validation?

Or maybe use celery to do the validation? But then what if the validation fails? How should the server inform the client that the validation has failed for some reason in the background?

0

There are 0 best solutions below