Make Django's collectstatic command forgiving

29 Jan · by Tim Kamanin · 3 min read

Have this ever happened to you? You run a python manage.py collecstatic command, it progresses for some time and then throws an error, something like:

ValueError: The file 'theme/startup/css/font/ytp-regular.eot' 
could not be found with 
<django.contrib.staticfiles.storage.ManifestStaticFilesStorage object at 0x10b47cc50>

Well, that means, your staticfiles storage collector couldn't find a file declared somewhere deep in CSS. Sometimes this error is a piece of useful information, but sometimes, it's a guaranteed pain, especially if you use some third-party themes, jquery plugins or as in my case, the Startup framework.

Okay, so now what? If you know that the file is essential you go and fix that missing part, but if you don't care and want the static collector to advance and ignore that missing file?

Well, you need The Forgiving Static Files Storage.

And here's how to make one. By default, in your settings.py STATICFILES_STORAGE is set to django.contrib.staticfiles.storage.ManifestStaticFilesStorage and it's the class that's responsible for our python manage.py collecstatic behavior.

Thus we could extend it and tell it to ignore missing files. Let's do this!

  1. Create a storage.py file inside a Django app. I like to have core app inside every Django project I start where I define such application wide logic, so in my case, the file's path is core/storage.py.

  2. Add the following contents to a file:

    from django.contrib.staticfiles.storage import ManifestStaticFilesStorage
    
    
    class ForgivingManifestStaticFilesStorage(ManifestStaticFilesStorage):
    
        def hashed_name(self, name, content=None, filename=None):
            try:
                result = super().hashed_name(name, content, filename)
            except ValueError:
                # When the fille is missing, let's forgive and ignore that.
                result = name
            return result
    
  3. In setting.py set STATICFILES_STORAGE as ForgivingManifestStaticFilesStorage:

    STATICFILES_STORAGE = 'core.storage.ForgivingManifestStaticFilesStorage'
    
  4. Run python manage.py collecstatic and see how nicely it finished!

Done!

UPDATE:

I've created a PyPI package based on this tutorial. The package is called django-forgiving-collectstatic and here's how to use it:

  1. Install from PyPI:

    pip install django-forgiving-collectstatic
    
  2. Set in your settings.py:

    STATICFILES_STORAGE = 'django_forgiving_collecstatic.storages.ForgivingManifestStaticFilesStorage'
    
  3. Run python manage.py collecstatic and never worry about missing static files.

Check it out on Github and PyPI.

Want to get more 🔥 tips like this one?

Subscribe to get notified about new dev tutorials