Hasan Ramezani
Hasan Ramezani

Reputation: 5194

Django dynamic models.FileField Storage

I have a model like this:

class Person(models.Model):
    name = models.Charfield(max_length¶=30)
    photo = models.FileField(upload_to='uploads/')

Is there any way to dynamically change the Storage class of photo field based on the value of the name field?

for example, I want to store the photo of the persons with the name xxx to FileSystemStorage¶ and for the others I want to use S3Storage

Upvotes: 6

Views: 2319

Answers (2)

S.K
S.K

Reputation: 530

I also had a similar use case. Update storage dynamically using the model field object_storage_name. Tried this below code by taking inspiration from the article https://medium.com/@hiteshgarg14/how-to-dynamically-select-storage-in-django-filefield-bc2e8f5883fd

class MediaDocument(models.Model):
    object_storage_name = models.CharField(max_length=255, null=True)
    file = DynamicStorageFileField(upload_to=mediadocument_directory_path)


class DynamicStorageFieldFile(FieldFile):

    def __init__(self, instance, field, name):
        super(DynamicStorageFieldFile, self).__init__(
            instance, field, name
        )
        if instance.object_storage_name == "alibaba OSS":
            self.storage = AlibabaStorage()
        else:
            self.storage = MediaStorage()


class DynamicStorageFileField(models.FileField):
    attr_class = DynamicStorageFieldFile

    def pre_save(self, model_instance, add):
        if model_instance.object_storage_name == "alibaba OSS":
            storage = AlibabaStorage()
        else:
            storage = MediaStorage()
        self.storage = storage
        model_instance.file.storage = storage
        file = super(DynamicStorageFileField, self
                     ).pre_save(model_instance, add)
        return file

It worked fine.

Upvotes: 5

Shakil
Shakil

Reputation: 4630

Yes, You can assign custom upload location for some specific file.

def my_upload_function(instance, filename):
    if instance.name === your_name:
        return your_location

    return generic_location


class Person(models.Model):
    name = models.Charfield(max_length¶=30)
    photo = models.FileField(upload_to=my_upload_function)

Upvotes: 0

Related Questions