How do I ignore static files of a particular app only with collectstatic?

django, django-staticfiles

Solution

I managed to solve this by subclassing Django finders like this:

PYTHON 2.X

from django.contrib.staticfiles import finders
from django.conf import settings


def add_ignores(ignore_patterns):
    ignore = settings.STATICFILES_FINDERS_IGNORE

    if ignore:
        if ignore_patterns:
            ignore_patterns.extend(ignore)
        else:
            ignore_patterns = ignore

    return ignore_patterns


class FileSystemFinderIgnore(finders.FileSystemFinder):
    def list(self, ignore_patterns):
        return super(FileSystemFinderIgnore, self).list(add_ignores(ignore_patterns))


class AppDirectoriesFinderIgnore(finders.AppDirectoriesFinder):
    def list(self, ignore_patterns):
        return super(AppDirectoriesFinderIgnore, self).list(add_ignores(ignore_patterns))


class DefaultStorageFinderIgnore(finders.DefaultStorageFinder):
    def list(self, ignore_patterns):
        return super(DefaultStorageFinderIgnore, self).list(add_ignores(ignore_patterns))

PYTHON 3.X

from django.contrib.staticfiles import finders
from django.conf import settings


def add_ignores(ignore_patterns):
    ignore = settings.STATICFILES_FINDERS_IGNORE

    if ignore:
        if ignore_patterns:
            ignore_patterns.extend(ignore)
        else:
            ignore_patterns = ignore

    return ignore_patterns


class FileSystemFinderIgnore(finders.FileSystemFinder):
    def list(self, ignore_patterns):
        return super().list(add_ignores(ignore_patterns))


class AppDirectoriesFinderIgnore(finders.AppDirectoriesFinder):
    def list(self, ignore_patterns):
        return super().list(add_ignores(ignore_patterns))


class DefaultStorageFinderIgnore(finders.DefaultStorageFinder):
    def list(self, ignore_patterns):
        return super().list(add_ignores(ignore_patterns))

and adding this to my settings:

STATICFILES_FINDERS_IGNORE = [
    '*.scss',
    '*.js',
]

Problem

Just to get this out of the way, if at all possible, I'd like to do this without nesting them all inside a directory with the app's name inside the app's static folder, it feels redundant. If it's the only way then such is life. I am using: ``` STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', ) ``` and: ``` STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage' ``` which compiles the JS and SASS when running collectstatic. These are both located in the APP_ROOT/static/ directory. The only 'problem' is that it brings along all the source sass and js files alongside it. At some point I'm going to be pushing this all to S3 and I'd like to avoid that if possible. I found that if you run: ``` python manage.py collectstatic -i sass -i js ``` It still compiles the JS and CSS files I specified, while leaving the rest of the 'source' files out. Unfortunately, it also ignores every js file in /admin/ as it matches /admin/js/ etc. I don't even know if that's likely to be a problem for this particular project, but I can foresee in the future other apps where I definitely will want to include static js/css kept in an app. What I'd like to be able to do is something like: ``` python manage.py collectstatic -i app_name/sass -i app_name/js ``` And as I mentioned at the top the easy solution is just to prefix my static files in the folder with app_name/, much like how django.contrib.admin does it. At this point however, you end up with a directory structure of PROJECT_ROOT/app_name/static/app_name/[js|sass|img|data]/ and I think it should be possible to avoid the redundancy. Then again, maybe it's the best option, so as to guarantee avoiding conflict with other apps? I've looked into writing custom storages and finders, and I think it's possible to roll my own. I wanted to check here though first, to see if this is a problem someone else has solved, or, to get a reality check if the overwhelming response is to just add the prefix directory. If I was to roll my own, the path I think I would take would be extending `django.contrib.staticfiles.finders.AppDirectoriesFinder` and overriding `list()`. I'm not yet positive this approach would work, I need to more trace how things progress from the collectstatic management command, so if anyone has done this or something simlilar before, or knows why it will/won't work, any help is appreciated. Thanks!

Original source