Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select models and fields via settings #114

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 explicitly 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 :code:`CLEANUP` is set and a model or field is not included in the :code:`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