Repository: django-cms/django-filer

Issue:
Running management commands fails when using ManifestStaticFilesStorage
I am running Django 1.8.7.

Some fields calls the `static` template tag in their `class Media`. This code gets executed when `INSTALLED_APPS` is processed. Since `collectstatic` is not run yet, resolving the path fails. If `collectstatic` has been run before, this does not happen.

The calls to `static` seem to be redundant. According to Django documentation media file paths are transformed into URLs automatically.

This also affects whitenoise users.



Discussion:
Just also ran into this problem. This commit broke it: https://github.com/divio/django-filer/commit/b29e7cc8d488f5c6c469d29e4027b369b64f60db

Here's the documentation that ferrix is referring to: https://docs.djangoproject.com/en/1.8/topics/forms/media/#form-asset-paths

Here's the exception:

```
vagrant@v-ston ~/ston> ./manage.py collectstatic
Traceback (most recent call last):
  File "./manage.py", line 11, in <module>
    django.setup()
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/django/__init__.py", line 18, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/django/apps/registry.py", line 108, in populate
    app_config.import_models(all_models)
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/django/apps/config.py", line 198, in import_models
    self.models_module = import_module(models_module_name)
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/importlib/__init__.py", line 109, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 2254, in _gcd_import
  File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
  File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1129, in _exec
  File "<frozen importlib._bootstrap>", line 1471, in exec_module
  File "<frozen importlib._bootstrap>", line 321, in _call_with_frames_removed
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/cmsplugin_filer_image/models.py", line 7, in <module>
    from filer.fields.image import FilerImageField
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/filer/fields/image.py", line 3, in <module>
    from filer.fields.file import (
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/filer/fields/file.py", line 23, in <module>
    class AdminFileWidget(ForeignKeyRawIdWidget):
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/filer/fields/file.py", line 83, in AdminFileWidget
    class Media:
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/filer/fields/file.py", line 85, in Media
    static('filer/js/popup_handling.js'),
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/django/contrib/staticfiles/templatetags/staticfiles.py", line 9, in static
    return staticfiles_storage.url(path)
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/django/contrib/staticfiles/storage.py", line 131, in url
    hashed_name = self.stored_name(clean_name)
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/django/contrib/staticfiles/storage.py", line 280, in stored_name
    cache_name = self.clean_name(self.hashed_name(name))
  File "/home/vagrant/virtualenvs/ston/lib/python3.4/site-packages/django/contrib/staticfiles/storage.py", line 94, in hashed_name
    (clean_name, self))
ValueError: The file 'filer/js/popup_handling.js' could not be found with <django.contrib.staticfiles.storage.ManifestStaticFilesStorage object at 0x7fcde9333048>.
```

I ran into this issue with whitenoise on heroku. I don't know if it is a good workaround, but I committed my local staticfiles/filer directory to my repository and sent them up to heroku with everything else.

My workaround is to first run a separate `collectstatic` without manifests and then again with manifests. This requires either two `settings.py` files or some more black belt magic.

:+1: 

Ran into this too while using Django Pipeline's `pipeline.storage.PipelineStorage` for STATICFILES_STORAGE. Per @ferrix's suggestion, I solved by creating a new environment w/ `STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'`, and running collectstatic with that environment, followed by a run with the real environment.

If static/media files are detected automatically in there, we can just remove them. But we need to be sure that it also work for special storage backends (e.g S3) where the static file might be on a other domain entirely. @ferrix do you happen to know if that would work.
Also we need to make sure there are no regressions for older versions of Django.

@stefanfoulis That is my use case exactly. Standard implementations of StaticFilesStorage are implicitly executed by `static` and the behavior has been described to do the implicit url transformation from Django 1.5 at least (ref: https://docs.djangoproject.com/en/1.5/topics/forms/media/#media-as-a-static-definition) and the offending commit b29e7cc is from 2015. So, this is a trivial change.

@stefanfoulis Please see here for the relevant django source code. All the way from 1.5
https://github.com/django/django/blob/1.5/django/forms/widgets.py#L71
to 1.9
https://github.com/django/django/blob/1.9/django/forms/widgets.py#L80

For everybody else: Setting DEBUG for the `collectstatic` run also works and saves you from running collectstatic twice.


Resolving patch:
diff --git a/filer/fields/file.py b/filer/fields/file.py
--- a/filer/fields/file.py
+++ b/filer/fields/file.py
@@ -5,7 +5,6 @@
 from django import forms
 from django.contrib.admin.widgets import ForeignKeyRawIdWidget
 from django.contrib.admin.sites import site
-from django.contrib.staticfiles.templatetags.staticfiles import static
 from django.core.urlresolvers import reverse
 from django.db import models
 from django.template.loader import render_to_string
@@ -83,15 +82,15 @@ def obj_for_value(self, value):
     class Media(object):
         css = {
             'all': [
-                static('filer/css/admin_filer.css')
+                'filer/css/admin_filer.css',
             ]
         }
         js = (
-            static('filer/js/libs/jquery.min.js'),
-            static('filer/js/libs/dropzone.min.js'),
-            static('filer/js/addons/dropzone.init.js'),
-            static('filer/js/addons/popup_handling.js'),
-            static('filer/js/addons/widget.js'),
+            'filer/js/libs/jquery.min.js',
+            'filer/js/libs/dropzone.min.js',
+            'filer/js/addons/dropzone.init.js',
+            'filer/js/addons/popup_handling.js',
+            'filer/js/addons/widget.js',
         )
 
 
diff --git a/filer/fields/folder.py b/filer/fields/folder.py
--- a/filer/fields/folder.py
+++ b/filer/fields/folder.py
@@ -5,7 +5,6 @@
 from django import forms
 from django.contrib.admin.sites import site
 from django.contrib.admin.widgets import ForeignKeyRawIdWidget
-from django.contrib.staticfiles.templatetags.staticfiles import static
 from django.core.urlresolvers import reverse
 from django.db import models
 from django.template.loader import render_to_string
@@ -79,7 +78,9 @@ def obj_for_value(self, value):
         return obj
 
     class Media(object):
-        js = (static('filer/js/addons/popup_handling.js'), )
+        js = (
+            'filer/js/addons/popup_handling.js',
+        )
 
 
 class AdminFolderFormField(forms.ModelChoiceField):


Test patch: