Skip to main content

Use and choose storages at runtime based on your logic for each model FileField instance separately.

Project description

tox CI PyPi Version Python Versions Django Versions pre-commit.ci status Code style: black Imports: isort

django-dynamic-storage

Have you ever wanted not to store every instance of FileFileds or ImageFileds of a model in one storage or one bucket of a storage?

Now you can, because I wanted that for my project.

prerequisites:

If your django version is earlier than 3.1 (<=3.0) then your database should be PostgreSQL otherwise you are good to go.

Usage:

pip install django-dynamic-storage

in storage.py:

from dynamic_storage.storage import DynamicStorageMixin

@deconstructible
class MyDynamicStorage(DynamicStorageMixin, AnyStorage):
	def init_params(self) -> dict:
		"""
		here you should return a dictionary of key value pairs that 
		later django-dynamic-storage could instantiate this class with
		"""
		return {"named_param1": self.named_param1, "named_param2": self.named_param2, ...}

AnyStorage can be a storage that you define yourself or import from django-storages.

in models.py:

from dynamic_storage.models import DynamicFileField, DynamicImageField

class MyModel(models.Model):
	"""
	DynamicFileField and DynamicImageField accept any options that django's native FileField and ImageField accept
	"""
	file = DynamicFileField()
	image = DynamicWagtailImageField()

Now your logic to take control of the storage where your content is going to be saved to:

obj = MyModel(file=file, image=image)
obj.file.destination_storage = MyDynamicStorage(named_param1="something", named_param2="another_thing")
obj.image.destination_storage = MyDynamicStorage(named_param1="foo", named_param2="bar")
obj.save()

or using signals:

(new to signals? learn how to connect them)

from dynamic_storage.signals import pre_dynamic_file_save

@receiver(pre_dynamic_file_save, sender=models.MyModel)
def decide_the_storage_to_save(
instance
, field_file
, to_storage
, *args,
 **kwargs
):
    if not to_storage:
    	# destination_storage is not set, so we set it here
        field_file.destination_storage = MyDynamicStorage(named_param1="something", named_param2="another_thing")
    elif to_storage == wrong_storage:
		# override the destination_storage set earlier
		field_file.destination_storage = MyAnotherDynamicStorage(named_param1="foo", named_param2="bar")

Performance penalty?!

Not even a bit!

HOW?

We are just using the django's built in JsonField instead of CharField  to store more data (init_params output) in addition to the path to the file.

so no extra queries, no extra steps, no performance penalty.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_dynamic_storage-0.1.5.tar.gz (5.2 kB view hashes)

Uploaded Source

Built Distribution

django_dynamic_storage-0.1.5-py3-none-any.whl (6.3 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page