django-castor icon indicating copy to clipboard operation
django-castor copied to clipboard

How to implement reference counting or garbage collection

Open beruic opened this issue 8 years ago • 2 comments

I like the looks of django-castor and consider using it in a project. However reading the caveats section of the README, I was wondering how difficult it would be to let django-castor have automatic reference counting? This would be my preferred solution to cleaning the storage.

I have been playing with the idea to implement two fields (names could be CastorFileField and CastorImageField) for the purpose, with a simple model as backing store for the counting, but I deemed this an inflexible solution because it would make it impossible to use castor for other fields that inherit from FileField or ImageField.

My next idea is to make django-castor store which models have saved files through the storage, and then make delete count from the database with these model references. Since the penalty is only big at delete time(at save time there's no counting, only addition of model reference if no already exists), I find it a promising design. A setting could be used to enable/disable this behaviour. However I currently see no way to let the storage know the model at save time. Perhaps __init__ or get_available_name could read it from it's caller?

This is all unfortunately out of my scope for now, and I'm therefore wondering how I can implement garbage collection. Thinking of it, being able to garbage collect a single file, would also make it possible to clean up upon deletion.

Does anyone have an idea how to achieve clean up without coding it manually to check each of your models using the django-castor storage? Perhaps inspecting all models at __init__ time?

beruic avatar Oct 08 '15 14:10 beruic

Heureka!

I have found a way to detect models that use CAS storage. Here used in a command:

from django.core.management.base import BaseCommand
from django.apps import apps
from django.db import models
from djcastor import CAStorage


class Command(BaseCommand):
    help = 'List all FieldFields in models, and mark the ones using CAStorage with a *'

    def handle(self, *args, **options):

        for model in apps.get_models():

            for field_name in model._meta.get_all_field_names():
                field = model._meta.get_field(field_name)

                if isinstance(field, models.FileField):
                    if isinstance(field.storage, CAStorage):
                        print('* ', end='')
                    else:
                        print('  ', end='')
                    print(model.__name__ + ':: ' + str(field_name) + ':\t' + type(field).__name__)

beruic avatar Oct 09 '15 10:10 beruic

It is also worth to take a look at https://github.com/un1t/django-cleanup/blob/master/django_cleanup/models.py#L90, as they do it with support for Django >= 1.6

beruic avatar Oct 09 '15 13:10 beruic