Skip to content

Commit

Permalink
Select models and fields via settings
Browse files Browse the repository at this point in the history
  • Loading branch information
stevelacey committed Jan 21, 2025
1 parent ffce153 commit 3b36485
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 2 deletions.
15 changes: 15 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,21 @@ mark a model for cleanup:
class MyModel(models.Model):
image = models.FileField()
Only cleanup selected fields
----------------------------
If you prefer to configure which fields django-cleanup will handle, you can use the :code:`CLEANUP` setting in your settings.py:

.. code-block:: py
CLEANUP = {
'model.name': {'field1', 'field2'}, # Only clean these fields for this model
'other.model': {'field3'} # Only clean field3 for other.model
}
The setting maps model names (in the format "app_label.model_name") to sets of field names that should be cleaned up.

Note that if CLEANUP is set and a model or field is not included in the CLEANUP setting, its files will not be cleaned up.

How to run tests
================
Install, setup and use pyenv_ to install all the required versions of cPython
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ pythonpath = [".", "src"]
addopts = ["-v", "--cov-report=term-missing", "--cov=django_cleanup"]
markers = [
"cleanup_selected_config: marks test as using the CleanupSelectedConfig app config",
"cleanup_settings: marks test as using the CLEANUP django setting",
"django_storage: change django storage backends"
]
9 changes: 7 additions & 2 deletions src/django_cleanup/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from collections import defaultdict

from django.apps import apps
from django.conf import settings
from django.db import models
from django.utils.module_loading import import_string

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

config = getattr(settings, "CLEANUP", {})
for model in apps.get_models():
if ignore_model(model, select_mode):
continue
Expand All @@ -36,8 +38,11 @@ def prepare(select_mode):
continue
opts = model._meta
for field in opts.get_fields():
if isinstance(field, models.FileField):
add_field_for_model(name, field.name, field)
if not isinstance(field, models.FileField):
continue
if config and field.name not in config.get(name, []):
continue
add_field_for_model(name, field.name, field)


def add_field_for_model(model_name, field_name, field):
Expand Down
3 changes: 3 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ def pytest_collection_modifyitems(items):

@pytest.fixture(autouse=True)
def setup_django_cleanup_state(request, settings):
settings_marker = request.node.get_closest_marker("cleanup_settings")
settings.CLEANUP = settings_marker.args[0] if settings_marker else None

for model in cache.cleanup_models():
suffix = f'_django_cleanup_{cache.get_model_name(model)}'
post_init.disconnect(None, sender=model,
Expand Down
44 changes: 44 additions & 0 deletions test/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,47 @@ def test__select_config__replace_file_with_file_ignore(picture):
new_image_path = os.path.join(django_settings.MEDIA_ROOT, random_pic_name)
assert product.image.path == new_image_path
#endregion


#region cleanup settings
@pytest.mark.cleanup_settings({'test.product': {'image'}})
def test_cleanup_settings_model_included(picture):
product = Product.objects.create(image=picture['filename'])
assert os.path.exists(picture['path'])
random_pic_name = get_random_pic_name()
product.image = random_pic_name
with transaction.atomic(get_using(product)):
product.save()
assert not os.path.exists(picture['path'])
assert product.image
new_image_path = os.path.join(django_settings.MEDIA_ROOT, random_pic_name)
assert product.image.path == new_image_path


@pytest.mark.cleanup_settings({'test.other_model': {'image'}})
def test_cleanup_settings_model_excluded(picture):
product = Product.objects.create(image=picture['filename'])
assert os.path.exists(picture['path'])
random_pic_name = get_random_pic_name()
product.image = random_pic_name
with transaction.atomic(get_using(product)):
product.save()
assert os.path.exists(picture['path']) # File should not be cleaned up
assert product.image
new_image_path = os.path.join(django_settings.MEDIA_ROOT, random_pic_name)
assert product.image.path == new_image_path


@pytest.mark.cleanup_settings({'test.product': {'other_field'}})
def test_cleanup_settings_field_excluded(picture):
product = Product.objects.create(image=picture['filename'])
assert os.path.exists(picture['path'])
random_pic_name = get_random_pic_name()
product.image = random_pic_name
with transaction.atomic(get_using(product)):
product.save()
assert os.path.exists(picture['path']) # File should not be cleaned up
assert product.image
new_image_path = os.path.join(django_settings.MEDIA_ROOT, random_pic_name)
assert product.image.path == new_image_path
#endregion

0 comments on commit 3b36485

Please sign in to comment.