I am using django-compresor for an app deployed on heroku with amazon S3 serving static files. Everything is working fine except that images in my css referenced in the background-image: url() are not rendered with with the correct path.
My static files are organized in the following directory structure:
-static
-myapp
-js
-css
-img
-bootstrap
-js
-css
-img
-othervendor
-js
-css
-img
Therefore, the path i am using in the url() is relative to the css file:
url("../img/icon.png")
All of my css files are compressed and moved to the CACHE folder in my static directory and the url to the CACHE directory is rendered correctly as:
https://mybucket.s3.amazonaws.com/static/CACHE/css/somehash.css
The problem is that the images in the css files url() are rendered as:
https://mybucket.s3.amazonaws.com/static/CACHE/img/imagefile.png
and it should be:
https://mybucket.s3.amazonaws.com/static/myapp/img/imagefile.png
or if the images were copied to the CACHE directory this would work:
https://mybucket.s3.amazonaws.com/static/CACHE/img/imagefile.png
My temporary fix is to change the paths of images in my css to the following and it works:
url("/static/foldername/img/icon.png")
I am new to django & compressor so i'm not sure what the correct behavior is supposed to be, but this does not seem to be correct. The way i see it, the problem can be fixed if i can get django compressor to do one of two things: 1)copy all images referenced in css url() to the CASHE/img directory OR 2)render the correct url represented by ../ Here is my setup:
The css files in my template are in a {% compress css %} block.
s3utils.py (used to make separate media and static directories in my bucket)
from storages.backends.s3boto import S3BotoStorage
StaticS3BotoStorage = lambda: S3BotoStorage(location='static')
StaticRootS3BotoStorage = lambda: S3BotoStorage(location='static')
MediaS3BotoStorage = lambda: S3BotoStorage(location='media')
MediaRootS3BotoStorage = lambda: S3BotoStorage(location='media')
settings.py
DEFAULT_FILE_STORAGE = 'myapp.settings.s3utils.MediaRootS3BotoStorage'
STATICFILES_STORAGE = 'myapp.settings.s3utils.StaticRootS3BotoStorage'
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME')
S3_URL = 'http://%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
MEDIA_URL = S3_URL+'media/'
MEDIA_ROOT = S3_URL+'media/'
STATIC_URL = S3_URL+'static/'
STATIC_ROOT = S3_URL+'static/'
COMPRESS_STORAGE = STATICFILES_STORAGE
COMPRESS_URL = STATIC_URL
COMPRESS_ROOT = STATIC_ROOT
Im thinking there must be some setting that tells compressor to copy css url("../img/image.png") to the CACHE/img directory???
I had the same issue!
for me It first seemed as if it was an issue with compressor. I changed my prefixed S3Storage Backend from
StaticS3Backend = lambda: S3BotoStorage(location='static')
to
class StaticS3Backend(S3BotoStorage):
location = 'static'
because the other method didn't set the location value right (It stayed empty)
This fixed the issue for me.
I have not found any good solution at all. Some good discussions here https://github.com/jezdez/django_compressor/issues/226
In your CSS file, use an absolute path that point to the image url on your Amazon S3 will make it work. But without saying, this is stupid. Why would I want my local development and testing environment all use the image from prod? Some times, it is not even acceptable. Say you want to change the image and test it for a while. (You can manually upload the new image to s3 and manually change all thousands of css references to this image to the new url. Again, stupid.)
A slightly better way is use {{STATIC_URL}} in your css to build an absolute path instead of relative path. Yes, you can use {{STATIC_URL}} if you add compressor.filters.template.TemplateFilter mentioned here https://django_compressor.readthedocs.org/en/1.3/settings/#base-settings . This solves multiple stage problem. But, it does not work for local development because you are not compressing here and if you do, you will have a hard time debugging.
Personally I feel having compressor.filters.template.TemplateFilter inside django-compressor is wrong. It should be part of django. An optional process that you can turn on for css and js.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With