I've been through the ringer getting my Django app setup on Heroku using Amazon s3 to host the static and media files. I've been following this guide https://www.caktusgroup.com/blog/2014/11/10/Using-Amazon-S3-to-store-your-Django-sites-static-and-media-files/ and what seems like thousands of other resources, collectstatic has worked and heroku is deploying it - but displays a 400 error. When I try and run it locally i get more info:
Attempted access to '/css/reset.css' denied.
This is the line that gets highlighted:
<link rel="stylesheet" type="text/css" href="{% static '/css/reset.css' %}">
I can load the static files direct from the URL if I grab it from my s3 admin panel so I figured it wasn't a bucket policy issue, I've messed around with https / http options but no joy. So I figure it must be the wrong path is being called somehow in the code - i just can't see where!
Any help much appreciated, I don't think I've blinked for about 4 hours straight.
Traceback:
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/storages/backends/s3boto.py" in _normalize_name
358. return safe_join(self.location, name)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/storages/backends/s3boto.py" in safe_join
59. raise ValueError('the joined path is located outside of the base path'
During handling of the above exception (the joined path is located outside of the base path component), another exception occurred:
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/devtop/webdev/projects/intro/intro/profiles/views.py" in index
14. return render(request, 'home.html', {'welcome':welcome})
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/shortcuts.py" in render
30. content = loader.render_to_string(template_name, context, request, using=using)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/loader.py" in render_to_string
68. return template.render(context, request)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/backends/django.py" in render
66. return self.template.render(context)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in render
207. return self._render(context)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/loader_tags.py" in render
177. return compiled_parent._render(context)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/templatetags/static.py" in render
105. url = self.url(context)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/templatetags/static.py" in url
102. return self.handle_simple(path)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/django/templatetags/static.py" in handle_simple
117. return staticfiles_storage.url(path)
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/storages/backends/s3boto.py" in url
487. name = self._normalize_name(self._clean_name(name))
File "/home/devtop/webdev/projects/intro/myvenv/lib/python3.5/site-packages/storages/backends/s3boto.py" in _normalize_name
361. name)
Exception Type: SuspiciousOperation at /
Exception Value: Attempted access to '/css/reset.css' denied.
settings.py
AWS_ACCESS_KEY_ID=os.environ.get('AWS_ACCESS_KEY_ID',None)
AWS_SECRET_KEY=os.environ.get('AWS_SECRET_KEY',None)
AWS_SECRET_ACCESS_KEY=os.environ.get('AWS_SECRET_KEY', None)
AWS_STORAGE_BUCKET_NAME = 'intro-story'
AWS_S3_HOST='s3.us-east-2.amazonaws.com'
AWS_S3_CUSTOM_DOMAIN = 's3.us-east-2.amazonaws.com/%s' % AWS_STORAGE_BUCKET_NAME
AWS_S3_SECURE_URLS = False
STATICFILES_LOCATION = 'static'
STATICFILES_STORAGE = 'custom_storages.StaticStorage'
STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, STATICFILES_LOCATION)
MEDIAFILES_LOCATION = 'media'
MEDIA_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, MEDIAFILES_LOCATION)
DEFAULT_FILE_STORAGE = 'custom_storages.MediaStorage'
try:
from .local_settings import *
except ImportError:
pass
local_settings.py
AWS_ACCESS_KEY_ID = "xxx"
AWS_SECRET_ACCESS_KEY = "yyy"
custom_storages.py
from django.conf import settings
from storages.backends.s3boto import S3BotoStorage
class StaticStorage(S3BotoStorage):
location = settings.STATICFILES_LOCATION
class MediaStorage(S3BotoStorage):
location = settings.MEDIAFILES_LOCATION
EDIT:
I managed to get it working by messing around with various values in the settings.py, but is still not right.
Here is all the stuff relating to static and media paths
STATICFILES_LOCATION = 'static'
MEDIAFILES_LOCATION = 'media'
import custom_storages
STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, STATICFILES_LOCATION)
STATICFILES_STORAGE = 'custom_storages.StaticStorage'
MEDIA_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, MEDIAFILES_LOCATION)
DEFAULT_FILE_STORAGE = 'custom_storages.MediaStorage'
Here is custom_storage that I'm importing:
from django.conf import settings
from storages.backends.s3boto import S3BotoStorage
class StaticStorage(S3BotoStorage):
location = settings.STATICFILES_LOCATION
class MediaStorage(S3BotoStorage):
location = settings.MEDIAFILES_LOCATION
Now, if i comment out
STATICFILES_STORAGE = 'custom_storages.StaticStorage'
It will load the static files from S3 and all is fine, BUT collectstatic fails. If I uncomment that line, collectstatic works but it gives an error when I try and load the site. The error is:
# Ensure final_path starts with base_path and that the next character after
# the final path is '/' (or nothing, in which case final_path must be
# equal to base_path).
base_path_len = len(base_path)
if (not final_path.startswith(base_path) or
final_path[base_path_len:base_path_len + 1] not in ('', '/')):
raise ValueError('the joined path is located outside of the base path' ...
' component')
return final_path.lstrip('/')
So clearly something is up with that custom_storage part but I have no idea what :/
Sorted! As expected it was something annoyingly simple but perhaps this will help anyone else who hits the same wall.
This:
<link rel="stylesheet" type="text/css" href="{% static '/css/reset.css' %}">
Needed to be this:
<link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}">
I.e. no leading slash in the href. Worked fine using local static files storage but broke the S3 link.
Related
I have installed open edx in two different machines, and access by the load balancer.
I have configured the Scorm xblock https://github.com/raccoongang/edx_xblock_scorm in open edx.
I want to upload scorm in azure blob so both machine access.
My configuration in lms.env.json and cms.env.json
"AZURE_ACCOUNT_KEY":"xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"AZURE_ACCOUNT_NAME": "myedx",
"AZURE_CONTAINER": "edx",
"DEFAULT_FILE_STORAGE": "openedx.core.storage.AzureStorageMedia",
"MEDIA_ROOT": "https://myedx.blob.core.windows.net/edx/",
"MEDIA_URL": "https://myedx.blob.core.windows.net/edx/",
My sotorage class
class AzureStorageMedia(AzureStorage):
account_name = settings.AZURE_ACCOUNT_NAME
account_key = settings.AZURE_ACCOUNT_KEY
azure_container = settings.AZURE_CONTAINER
expiration_secs = None
location = 'media'
file_overwrite = False
My error
resp = descriptor.handle(handler, req, suffix)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/xblock/mixins.py", line 89, in handle
return self.runtime.handle(self, handler_name, request, suffix)
File "/edx/app/edxapp/edx-platform/common/lib/xmodule/xmodule/x_module.py", line 1347, in handle
return super(MetricsMixin, self).handle(block, handler_name, request, suffix=suffix)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/xblock/runtime.py", line 1037, in handle
results = handler(request, suffix)
File "/edx/app/edxapp/edx_xblock_scorm/scormxblock/scormxblock.py", line 164, in studio_submit
os.mkdir(SCORM_ROOT)
OSError: [Errno 2] No such file or directory: 'https://myedx.blob.core.windows.net/edx/scorm'
How to solve this error.
I want to print / get the full path of an ImageField in django
photos = Photo.objects.all()
for photo in photos:
print(settings.MEDIA_ROOT + photo.image.path)
break
Bu I get this:
print(settings.MEDIA_ROOT + photo.image.file)
File "/home/juan/Desktop/juan/dev/yas/yas_django/venv/lib/python3.6/site-packages/django/db/models/fields/files.py", line 43, in _get_file
self._file = self.storage.open(self.name, 'rb')
File "/home/juan/Desktop/juan/dev/yas/yas_django/venv/lib/python3.6/site-packages/django/core/files/storage.py", line 36, in open
return self._open(name, mode)
File "/home/juan/Desktop/juan/dev/yas/yas_django/venv/lib/python3.6/site-packages/django/core/files/storage.py", line 224, in _open
return File(open(self.path(name), mode))
File "/home/juan/Desktop/juan/dev/yas/yas_django/venv/lib/python3.6/site-packages/django/core/files/storage.py", line 323, in path
return safe_join(self.location, name)
File "/home/juan/Desktop/juan/dev/yas/yas_django/venv/lib/python3.6/site-packages/django/utils/_os.py", line 46, in safe_join
'component ({})'.format(final_path, base_path))
django.core.exceptions.SuspiciousFileOperation: The joined path (/images/photos/2013/3/image_1) is located outside of the base path component (/home/juan/Desktop/juan/dev/yas/yas_django/media)
What is going on here? This is in my settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
The same happens if I print image.url or image.file. What I want to get is the full path to the image in order to open it with a third party lib.
I'm in the process of integrating Django_hosts. I have the front end URLs and the admin URLs successfully integrated and working, but my REST API URLs are still inaccessible due to this error:
'NoReverseMatch at /en/api/'
The error is traced to Django/urls/base.py, but I'm not sure what is triggering it:
Traceback (most recent call last):
File "/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/lib/python3.6/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
resolved_login_url = resolve_url(login_url or settings.LOGIN_URL)
File "/lib/python3.6/site-packages/django/shortcuts.py", line 148, in resolve_url
return reverse(to, args=args, kwargs=kwargs)
File "/lib/python3.6/site-packages/django/urls/base.py", line 86, in reverse
raise NoReverseMatch("%s is not a registered namespace" % key)
django.urls.exceptions.NoReverseMatch: 'admin' is not a registered namespace
These are my hosts.py and api_urls.py files:
# hosts.py
host_patterns = patterns(
'',
host(r'www', settings.ROOT_URLCONF, name='www'),
host(r'admin', 'Project.admin_urls', name='admin'),
host(r'api', 'Project.api_urls', name='api'),
)
# api_urls.py
urlpatterns += i18n_patterns (
path('session_security/', include('session_security.urls')),
path('', include('Project.apps.api.urls'), name='api'),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Also, to kill two birds with one stone, when attempting to convert this url:
{% url 'profile' request.user.id %}
to this url:
{% host_url 'profile' host 'www' request.user.id %}
It fails throwing a NoReverseMatch error with no arguments, as if the arguments are ignored.
Any help from someone knowledgeable about this package or either of these issues would be appreciated.
Thanks.
Update
I resolved this error by including admin.site urls within the api_urls.py file:
# api_urls.py
urlpatterns += i18n_patterns (
path('session_security/', include('session_security.urls')),
path('', include('Project.apps.api.urls'), name='api'),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
path('', admin.site.urls, name='admin'), <--This is key, but not sure exactly why.
However, now I've run into something strange, which isn't exactly an error, but effectively acts as one for my use case. The API seems to no longer recognize request.user, so that even if a user is logged in, the API thinks he is AnonymousUser.
*Both API and Admin subdomains not recognizing logged in user. Seems to be something to do with SESSION cookie...
I'm getting a very strange error that got me really stuck for many hours now.
I did my deploy with Heroku for the first time and am using S3 for Media files. First thing I noticed was that I never had a migration working successfully after installing boto and django-storages-redux, not sure why. Anyway I kept going.
My configurations seemed to be working in AWS, since my staticfiles did go to my bucket the first time I tried it, but I got some img files not coming through, so I decided to reinstall boto and django-registration-redux (to see if it would migrate properly).
In the end it never migrated as expected and now I'm getting the following error:
UnboundLocalError: local variable 'region_name' referenced before assignment
in my BOTO package when collectstatic.
I don't understand why migrate won't work and why I started to get this error when I re-installed boto and django-storages-redux.
terminal:
You have requested to collect static files at the destination
location as specified in your settings.
This will overwrite existing files!
Are you sure you want to do this?
Type 'yes' to continue, or 'no' to cancel: yes
Traceback (most recent call last):
File "/Users/Alex/Desktop/Allugare/src/manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/django/core/management/__init__.py", line 367, in execute_from_command_line
utility.execute()
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/django/core/management/__init__.py", line 359, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/django/core/management/base.py", line 294, in run_from_argv
self.execute(*args, **cmd_options)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/django/core/management/base.py", line 345, in execute
output = self.handle(*args, **options)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 193, in handle
collected = self.collect()
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 124, in collect
handler(path, prefixed_path, storage)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 349, in copy_file
if not self.delete_file(path, prefixed_path, source_storage):
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 255, in delete_file
if self.storage.exists(prefixed_path):
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/storages/backends/s3boto.py", line 439, in exists
if self.entries:
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/storages/backends/s3boto.py", line 302, in entries
for entry in self.bucket.list(prefix=self.location))
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/storages/backends/s3boto.py", line 301, in <genexpr>
self._entries = dict((self._decode_name(entry.key), entry)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/s3/bucketlistresultset.py", line 34, in bucket_lister
encoding_type=encoding_type)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/s3/bucket.py", line 473, in get_all_keys
'', headers, **params)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/s3/bucket.py", line 399, in _get_all
query_args=query_args)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/s3/connection.py", line 668, in make_request
retry_handler=retry_handler
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/connection.py", line 1071, in make_request
retry_handler=retry_handler)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/connection.py", line 927, in _mexe
request.authorize(connection=self)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/connection.py", line 377, in authorize
connection._auth_handler.add_auth(self, **kwargs)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/auth.py", line 755, in add_auth
**kwargs)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/auth.py", line 574, in add_auth
string_to_sign = self.string_to_sign(req, canonical_request)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/auth.py", line 514, in string_to_sign
sts.append(self.credential_scope(http_request))
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/auth.py", line 496, in credential_scope
region_name = self.determine_region_name(http_request.host)
File "/Users/Alex/Desktop/allugare/lib/python3.5/site-packages/boto/auth.py", line 690, in determine_region_name
return region_name
UnboundLocalError: local variable 'region_name' referenced before assignment
settings.py:
...
INSTALLED_APPS = (
#DJANGO APPS
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
#THIRD PARTY APPS
'allauth',
'allauth.account',
'allauth.socialaccount',
#Social Authentications
'allauth.socialaccount.providers.facebook',
# 'allauth.socialaccount.providers.instagram',
# 'allauth.socialaccount.providers.twitter',
'crispy_forms',
'django_messages',
'storages',
#MY APPS
'lares',
'mensagens',
'profiles',
)
...
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static-live", "static")
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "static-live", "media")
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
AWS_ACCESS_KEY_ID = "***"
AWS_SECRET_ACCESS_KEY = "***"
AWS_FILE_EXPIRE = 200
AWS_PRELOAD_METADATA = True
AWS_QUERYSTRING_AUTH = True
DEFAULT_FILE_STORAGE = 'allugare.utils.MediaRootS3BotoStorage'
STATICFILES_STORAGE = 'allugare.utils.StaticRootS3BotoStorage'
# DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_STORAGE_BUCKET_NAME = 's3allugare'
S3DIRECT_REGION = 'sa-east-1'
S3_URL = '//%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
MEDIA_URL = '//%s.s3.amazonaws.com/media/' % AWS_STORAGE_BUCKET_NAME
MEDIA_ROOT = MEDIA_URL
STATIC_URL = S3_URL + 'static/'
ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/'
AWS_S3_HOST = 'sa-east-1.amazonaws.com'
import datetime
two_months = datetime.timedelta(days=61)
date_two_months_later = datetime.date.today() + two_months
expires = date_two_months_later.strftime("%A, %d %B %Y 20:00:00 GMT")
AWS_HEADERS = {
'Expires': expires,
'Cache-Control': 'max-age=%d' % (int(two_months.total_seconds()), ),
}
wsgi.py
"""
WSGI config for allugare project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "allugare.settings")
application = get_wsgi_application()
utils.py
from storages.backends.s3boto import S3BotoStorage
StaticRootS3BotoStorage = lambda: S3BotoStorage(location='static') # S3 bucket name -> static
MediaRootS3BotoStorage = lambda: S3BotoStorage(location='media') # S3 bucket name -> static
Okay, here's the thing, if you're not using the default region of AWS you have to be careful when updating your region, since the S3's has different formats depending on the region.
I'm in South America, thus I'm using sa-east-1 (for São Paulo).
To me it worked when I changed the setting:
AWS_S3_HOST = 'sa-east-1.amazonaws.com'
to
AWS_S3_HOST = 's3-sa-east-1.amazonaws.com'
Enjoy!
So when i try accessing a certain image on S3 from my browser everything works fine. But when python is doing it i get a SuspiciousOperation error.
My static folder is public on S3 so i really have no idea where this is coming from.
Publication.objects.get(id=4039).cover.url
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/vagrant/.pyenv/versions/blook/lib/python2.7/site-packages/django/db/models/fields/files.py", line 64, in _get_url
return self.storage.url(self.name)
File "/home/vagrant/.pyenv/versions/blook/lib/python2.7/site-packages/queued_storage/backends.py", line 291, in url
return self.get_storage(name).url(name)
File "/home/vagrant/.pyenv/versions/blook/lib/python2.7/site-packages/queued_storage/backends.py", line 115, in get_storage
elif cache_result is None and self.remote.exists(name):
File "/home/vagrant/.pyenv/versions/blook/lib/python2.7/site-packages/storages/backends/s3boto.py", line 410, in exists
name = self._normalize_name(self._clean_name(name))
File "/home/vagrant/.pyenv/versions/blook/lib/python2.7/site-packages/storages/backends/s3boto.py", line 341, in _normalize_name
name)
SuspiciousOperation: Attempted access to 'http:/s3-eu-west-1.amazonaws.com/xpto/static/images/default-image.png' denied.
My settings:
AWS_S3_SECURE_URLS = True # use http instead of https
S3_URL = 'http://s3-eu-west-1.amazonaws.com/%s' % AWS_STORAGE_BUCKET_NAME
MEDIA_ROOT = 'media/'
STATIC_ROOT = '/static/'
STATIC_URL = S3_URL + STATIC_ROOT
MEDIA_URL = S3_URL + '/' + MEDIA_ROOT
For now i can work around it, but that is not a long term solution. any ideas?
Danigosa's answer in this thread is the answer:
django-storages and amazon s3 - suspiciousoperation
Create a special storage class as outlined in this post:
Using Amazon S3 to store your Django sites static and media files.
Then override _normalize_name like this:
from django.conf import settings
from storages.backends.s3boto3 import S3Boto3Storage
class StaticStorage(S3Boto3Storage):
location = settings.STATICFILES_LOCATION
def _clean_name(self, name):
return name
def _normalize_name(self, name):
if not name.endswith('/'):
name += "/"
name = self.location + name
return name
class MediaStorage(S3Boto3Storage):
location = settings.MEDIAFILES_LOCATION
def _clean_name(self, name):
return name
def _normalize_name(self, name):
if not name.endswith('/'):
name += "/"
name = self.location + name
return name
Finally - (on Python 3 at least) DON'T use
{% load static from staticfiles %}
in your templates.
Stick with:
{% load static %}
I recently faced the same issue. Tried all the available solutions. Realised that the issue was with the '/' that I had added while calling static files. Like this, "{% static '/path/to/static/file' %}", changed this to "{% static 'path/to/static/file' %}"