Skip to content

Commit c2f597a

Browse files
committed
Select models and fields via settings
1 parent ffce153 commit c2f597a

File tree

5 files changed

+70
-2
lines changed

5 files changed

+70
-2
lines changed

README.rst

+15
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,21 @@ mark a model for cleanup:
157157
class MyModel(models.Model):
158158
image = models.FileField()
159159
160+
Only cleanup selected fields
161+
----------------------------
162+
If you prefer to explicitly configure which fields django-cleanup will handle, you can use the :code:`CLEANUP` setting in your settings.py:
163+
164+
.. code-block:: py
165+
166+
CLEANUP = {
167+
'model.name': {'field1', 'field2'}, # Only clean these fields for this model
168+
'other.model': {'field3'} # Only clean field3 for other.model
169+
}
170+
171+
The setting maps model names (in the format "app_label.model_name") to sets of field names that should be cleaned up.
172+
173+
Note that if :code:`CLEANUP` is set and a model or field is not included in the :code:`CLEANUP` setting, its files will not be cleaned up.
174+
160175
How to run tests
161176
================
162177
Install, setup and use pyenv_ to install all the required versions of cPython

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,6 @@ pythonpath = [".", "src"]
4949
addopts = ["-v", "--cov-report=term-missing", "--cov=django_cleanup"]
5050
markers = [
5151
"cleanup_selected_config: marks test as using the CleanupSelectedConfig app config",
52+
"cleanup_settings: marks test as using the CLEANUP django setting",
5253
"django_storage: change django storage backends"
5354
]

src/django_cleanup/cache.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from collections import defaultdict
33

44
from django.apps import apps
5+
from django.conf import settings
56
from django.db import models
67
from django.utils.module_loading import import_string
78

@@ -28,6 +29,7 @@ def prepare(select_mode):
2829
if FIELDS: # pragma: no cover
2930
return
3031

32+
config = getattr(settings, "CLEANUP", {})
3133
for model in apps.get_models():
3234
if ignore_model(model, select_mode):
3335
continue
@@ -36,8 +38,11 @@ def prepare(select_mode):
3638
continue
3739
opts = model._meta
3840
for field in opts.get_fields():
39-
if isinstance(field, models.FileField):
40-
add_field_for_model(name, field.name, field)
41+
if not isinstance(field, models.FileField):
42+
continue
43+
if config and field.name not in config.get(name, []):
44+
continue
45+
add_field_for_model(name, field.name, field)
4146

4247

4348
def add_field_for_model(model_name, field_name, field):

test/conftest.py

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ def pytest_collection_modifyitems(items):
2121

2222
@pytest.fixture(autouse=True)
2323
def setup_django_cleanup_state(request, settings):
24+
settings_marker = request.node.get_closest_marker("cleanup_settings")
25+
settings.CLEANUP = settings_marker.args[0] if settings_marker else None
26+
2427
for model in cache.cleanup_models():
2528
suffix = f'_django_cleanup_{cache.get_model_name(model)}'
2629
post_init.disconnect(None, sender=model,

test/test_all.py

+44
Original file line numberDiff line numberDiff line change
@@ -432,3 +432,47 @@ def test__select_config__replace_file_with_file_ignore(picture):
432432
new_image_path = os.path.join(django_settings.MEDIA_ROOT, random_pic_name)
433433
assert product.image.path == new_image_path
434434
#endregion
435+
436+
437+
#region cleanup settings
438+
@pytest.mark.cleanup_settings({'test.product': {'image'}})
439+
def test_cleanup_settings_model_included(picture):
440+
product = Product.objects.create(image=picture['filename'])
441+
assert os.path.exists(picture['path'])
442+
random_pic_name = get_random_pic_name()
443+
product.image = random_pic_name
444+
with transaction.atomic(get_using(product)):
445+
product.save()
446+
assert not os.path.exists(picture['path'])
447+
assert product.image
448+
new_image_path = os.path.join(django_settings.MEDIA_ROOT, random_pic_name)
449+
assert product.image.path == new_image_path
450+
451+
452+
@pytest.mark.cleanup_settings({'test.other_model': {'image'}})
453+
def test_cleanup_settings_model_excluded(picture):
454+
product = Product.objects.create(image=picture['filename'])
455+
assert os.path.exists(picture['path'])
456+
random_pic_name = get_random_pic_name()
457+
product.image = random_pic_name
458+
with transaction.atomic(get_using(product)):
459+
product.save()
460+
assert os.path.exists(picture['path']) # File should not be cleaned up
461+
assert product.image
462+
new_image_path = os.path.join(django_settings.MEDIA_ROOT, random_pic_name)
463+
assert product.image.path == new_image_path
464+
465+
466+
@pytest.mark.cleanup_settings({'test.product': {'other_field'}})
467+
def test_cleanup_settings_field_excluded(picture):
468+
product = Product.objects.create(image=picture['filename'])
469+
assert os.path.exists(picture['path'])
470+
random_pic_name = get_random_pic_name()
471+
product.image = random_pic_name
472+
with transaction.atomic(get_using(product)):
473+
product.save()
474+
assert os.path.exists(picture['path']) # File should not be cleaned up
475+
assert product.image
476+
new_image_path = os.path.join(django_settings.MEDIA_ROOT, random_pic_name)
477+
assert product.image.path == new_image_path
478+
#endregion

0 commit comments

Comments
 (0)