django icon indicating copy to clipboard operation
django copied to clipboard

Fixed #26029 -- Added STORAGES setting

Open jwygoda opened this issue 2 years ago • 8 comments

I'd like to introduce a file storage registry similar to BaseConnectionHandler (django/utils/connection.py) and EngineHandler (django/template/utils.py).

Example settings.py snippet:

STORAGES = {  # rename to FILE_STORAGES to make it more explictit?
    'example': {
        'BACKEND': 'django.core.files.storage.FileSystemStorage',
        'OPTIONS': {
            'location': '/example',
            'base_url': '/example/',
        },
    },
}

Changes introduced by this pr are backward compatible. Users can still use existing settings to configure static and media storages.

Currently storages can be retrieved from the following objects:

django/core/files/storage.py:

  • get_storage_class
  • DefaultStorage
  • default_storage

django/contrib/staticfiles/storage.py:

  • ConfiguredStorage
  • staticfiles_storage

What do you think about deprecating them?

I'll write tests and docs if this approach is acceptable.

jwygoda avatar Apr 18 '22 12:04 jwygoda

I wrote some tests and docs. Should I deprecate stuff used for retrieving storages backends?

jwygoda avatar May 17 '22 10:05 jwygoda

@felixxm Thanks for the review! I've deprecated get_storage_class. Both DefaultStorage and ConfiguredStorage use this method so we'll get a deprecation warning from there. Should I deprecate these classes separately with custom deprecation messages?

jwygoda avatar Jul 27 '22 11:07 jwygoda

Both DefaultStorage and ConfiguredStorage use this method so we'll get a deprecation warning from there. Should I deprecate these classes separately with custom deprecation messages?

Yes we should deprecate them separately. Also, they shouldn't use deprecated settings.

felixxm avatar Jul 28 '22 05:07 felixxm

@felixxm DefaultStorage and ConfiguredStorage need to stay after all because default_storage and staticfiles_storage depend on settings and need to be lazy. I've deprecated STATICFILES_STORAGE and DEFAULT_FILE_STORAGE, wrote tests and docs. We may consider deprecating MEDIA_ROOT, MEDIA_URL, FILE_UPLOAD_PERMISSIONS, FILE_UPLOAD_DIRECTORY_PERMISSIONS, STATIC_ROOT and STATIC_URL because they can be confiured with OPTIONS in STORAGES.

jwygoda avatar Jul 29 '22 12:07 jwygoda

@felixxm I've applied requested changes, it's ready for review.

jwygoda avatar Aug 16 '22 09:08 jwygoda

@carltongibson Can we tackle the storage argument to FileField in a separate ticket?

Which shortcut do you mean? Is it settings.STORAGES["file_storage"]? If so see https://github.com/django/django/pull/15610/files#diff-1d5b04b0d2298a5675c19aeca9f82d3b5c08870a515f9c5063b77294279365beR2654

jwygoda avatar Aug 26 '22 20:08 jwygoda

Hi @jwygoda — sorry for the slow reply. I was ill.

Can we tackle the storage argument to FileField in a separate ticket?

I think 🤔 it's just a docs example — no other changes needed no? — so it would be good to include if you've not totally run out of steam 🙂 — If you have then, we can follow-up yes.

Which shortcut do you mean? Is it settings.STORAGES["file_storage"]?

No. See the comment:1 on the ticket, where have this: FileField(storage='myapp.test.a') with ...if myapp.test.a ... were in the configuration dictionary... — I'm not sure this additional API is needed, but we should decide that before leaving it (as otherwise we miss the window.)

Thanks for the effort here!

carltongibson avatar Sep 06 '22 07:09 carltongibson

No worries @carltongibson, hope you're feeling better now. I've updated the docs with an example usage of storages in FileField. I didn't add tests because it relies on the existing functionality of using callable in the storage kwarg. I'd prefer using a key from the STORAGES setting to specify the storage. I'd implement it by adding following to FileField.__init__:

from django.core.files import storages

self.storage = storages.get(self.storage, self.storage)

The only problem I have with this approach is that STORAGES keys can have any type that is immutable but it'll usually be a string and strings are prone to typos. Say someone has STORAGES with default key and a typo in FileField's storage kwarg, e.g. dfault. They wouldn't get an error until the first operation on the storage object, a string in this case. We could mitigate this problem by only allowing strings in STORAGES keys or requiring FileField.storage to be a subclass of Storage. Please let me know what you think about this, maybe I'm overthinking.

jwygoda avatar Sep 11 '22 15:09 jwygoda

Is there anything else needed to get this merged? @carltongibson @felixxm

jwygoda avatar Oct 18 '22 20:10 jwygoda

Hi @jwygoda — thanks for rebasing.

There's the failure you'll see...

ImportError: cannot import name 'StorageHandler' from 'django.core.files.storage' (/Users/carlton/Projects/Django/django/django/core/files/storage/init.py

Is there anything else needed to get this merged?

The ticket-26029 was marked as Patch needs improvement and Needs tests, so it wouldn't show up on the review queue. I've unchecked those now, so if you can fix the test failures I can take a look again next week or so.

carltongibson avatar Nov 17 '22 11:11 carltongibson

Hi @carltongibson, It's fixed now.

jwygoda avatar Nov 22 '22 08:11 jwygoda

Great thanks. You're on my list. 🥳

carltongibson avatar Nov 22 '22 08:11 carltongibson

Hey @jwygoda, I wanted to know if this PR is stable to be merged. I am planning to use the file storage registry for my contribution #15848.

bhavya-tech avatar Dec 18 '22 05:12 bhavya-tech

Hey @jwygoda, I wanted to know if this PR is stable to be merged. I am planning to use the file storage registry for my contribution #15848.

I think you can help the process of merge reviewing this PR 🙂

pauloxnet avatar Dec 18 '22 07:12 pauloxnet

@bhavya-tech This pr is ready for review.

jwygoda avatar Dec 21 '22 10:12 jwygoda

Yeah, I've struggled for a while with override_settings signal but it seems to be working now. EngineHandler works similarly to BaseConnectionHandler (reseted in clear_cache_handlers signal) and EngineHandler (reset_template_engines) so take a closer look at these. Take your time, better save than sorry.

jwygoda avatar Dec 22 '22 13:12 jwygoda

I pushed final edits and added release notes.

felixxm avatar Jan 12 '23 08:01 felixxm