Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django-compressor: CSS images with path relative to folder

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???

like image 605
Arctelix Avatar asked Mar 12 '13 14:03

Arctelix


2 Answers

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.

like image 179
rosner Avatar answered Sep 19 '22 19:09

rosner


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.

like image 20
Gordon Sun Avatar answered Sep 23 '22 19:09

Gordon Sun