Django MEDIA_URL again ... Unhandle - django

my settings.py file
MEDIA_ROOT = '/home/path/to/htdocs/mysite/public/media/'
MEDIA_URL = '/site_media/'
ADMIN_MEDIA_PREFIX = '/media/'
in site_media i have my images and CSS
...href="{{ MEDIA_URL }}/style.css" ... (with {{ MEDIA_URL }}style.css is this same)
after render it look like this
href="/site_media/style.css"
but at http://example.com/site_media/style.css there is Unhandled Exception (i thing no url mapped in urls.py)
everything is work fine in DEBUG mode because i have this in urls.py
if settings.DEBUG:
urlpatterns += patterns('',
(r'^media/(.*)$', 'django.views.static.serve', {'document_root': os.path.join(os.path.dirname(__file__), 'media')}),
(r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': os.path.join(os.path.dirname(__file__), 'site_media')}),
)
but what I need to do when DEBUG = False

what is happening is that in DEBUG mode django serves your style.css file. You tell it to do that with this line
(r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': os.path.join(os.path.dirname(__file__), 'site_media')}),
)
But this line does not go into the urlpatterns variable when debug is false. To test that try to access localhost:8000/site_media/style.css when debug is true (should work) and when it is false (will give a 404 error).
You could just leave out the
if settings.DEBUG:
part, but that means that django would still serve static files and that is not recommended in production for performance reasons.
In a production setup you should use a different webserver to serve your static files. I have had good experiences with nginx running in front of apache.
This is an excellent tutorial which shows you how to create such a setup:
http://www.ventanazul.com/webzine/tutorials/django-deployment-guide-ubuntu
Be prepared though that creating a production setup is not quite as painless as just typing python manage.py runserver. I have also heard good things about using nginx together with gunicorn and that that makes setting up a production server much simpler, but have no experience with it myself.

You need to serve them somehow yourself.
http://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-from-a-dedicated-server
In production, use something like Apache or Nginx to serve your static files.
Basically, you map a URL (in your case /site_media/) in the server to a folder on your server (like wherever your media directory is now) and you're done. All requests to /site_media/ now don't go to your app but go searching the directory for static files to serve.
Implementation depends on which server setup you go for.

Related

Wagtail {{document.url}} is returning a 404 for user-uploaded files, in production

I've inherited a Wagtail CMS project but have been unable to solve an issue relating to document uploads.
Having uploaded a file through the CMS, it arrives in the documents directory /var/www/example.com/wagtail/media/documents/test_pdf.pdf which maps to the /usr/src/app/media/documents/test_pdf.pdf directory inside the docker container.
In the front end (and within the Wagtail dashboard) the document.url resolves to https://example.com/documents/9/test_pdf.pdf/ which returns a 404. Obviously the model number segment is missing from the file path above, but I read on a forum that
In Wagtail, documents are always served through a Django view (wagtail.wagtaildocs.views.serve.serve) so that we can perform additional processing on document downloads
so perhaps this, in itself, is not an issue.
There are a couple of lines in urls.py file which look correct:
urlpatterns = [
url(r'^django-admin/', admin.site.urls),
url(r'^admin/', include(wagtailadmin_urls)),
url(r'^documents/', include(wagtaildocs_urls)),
url(r'^search/$', search_views.search, name='search'),
url(r'^sitemap\.xml$', sitemap),
url(r'', include(wagtail_urls)),
# url(r'^pages/', include(wagtail_urls)),
]
if settings.DEBUG:
...
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
and in base.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/
So, my hunch is one of either:
Uploads being stored incorrectly, in a single folder rather than in subdirectories by model
The routing to this “virtual” directory is broken, so it’s breaking at the "check permissions" stage (but I couldn't figure out how routing works in Django) and returning the 404
The web server is incorrectly configured, so whilst the “virtual” URL is fine it’s actually the file URL which is broken and THIS causes the 404 (my nginx contains a /media/ location but not a /documents/ location, as I would have expected)
Something else entirely (my next step is to pull a copy down to my own machine and see if the issue still occurs)
I appreciate there isn't much to go on here but I'm hoping that someone might be able to give me some pointers as to what else I should check, as I've been banging my head against this for most of the day.
My background is with Ruby on Rails so, as with that framework, I've a feeling that there is a lot of "magic" happening behind-the-scenes that is making it very tricky to figure out what's going on.
Thanks!
You are able to see documents while developing because of
if settings.DEBUG:
...
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Like static files media files should be handled on server level. For example, if you are using GCP you need to update your app.yaml and add media/ the same way as static/
...
handlers:
- url: /static
static_dir: static/
- url: /media
static_dir: media/
...

How to configure Django's "staticfiles" app to list directory contents?

I'm using Django's built-in web server, in DEBUG mode.
This is part of my settings.py:
STATIC_ROOT = '/home/user/static_root'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
'/abs/path/to/static/dir',
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
If I access http://localhost:8000/static/png/, I would expect to see a list of files available in /abs/path/to/static/dir/png. Instead I get a 404 error "Directory indexes are not allowed here."
Now if I access the files directly, e.g. http://localhost:8000/static/png/test.png, it works.
I've already checked some answers (here) without success.
So, does anyone know how to configure Django such that the staticfiles app lists directory contents?
Just for completeness since it might help others, this is what I did to solve the problem.
Following #Hedde's answer, I went to use show_indexes:
settings.py
Kept all the configuration the same (i.e. all the STATIC* variables)
Removed 'django.contrib.staticfiles' from INSTALLED_APPS
The problem is that I cannot specify the show_indexes parameter using Django's "built-in" method for static file configuration (via settings.py). By having 'django.contrib.staticfiles' in INSTALLED_APPS, Django would create the static file handler with show_indexes = False, ignoring my urlpatterns.
urls.py
Added the following to urlpatterns:
url(regex = r'^%s(?P<path>.*)$' % settings.STATIC_URL[1:],
view = 'django.views.static.serve',
kwargs = {'document_root': '/abs/path/to/static/dir',
'show_indexes' : True})
'show_indexes': True
As per the documentation
From https://docs.djangoproject.com/en/1.5/ref/views/#django.views.static.serve ...
static.serve(request, path, document_root, show_indexes=True)
Those files are not meant to be served by django. Show indexes is a configuration parameter of apache/nginx.
In production, with nginx, just add to the static serving part :
location ^~ /static/ {
autoindex on;
root /var/www/static_dir;
if ($query_string) {
expires max;
}
}
For dev environnement, Hedde's answer is indeed the good answer, but the display may not be the exact same than the one offered by your HTTP server. Don't rely on it's look&feel.

Serving Django Static Content based on DEBUG status

I have recently set up our project to serve static and media files from Amazon S3. This in turn has made our project serve all content from S3 even when working locally.
Our static settings are set to the following to work with S3:
STATIC_ROOT = "/%s/" % STATIC_S3_PATH
STATIC_URL = '//s3.amazonaws.com/%s/static/' % AWS_STORAGE_BUCKET_NAME
And in the URLs conf file we have added the following to match the Django documentation:
if settings.DEBUG:
urlpatterns += patterns('django.contrib.staticfiles.views',
url(r'^static/(?P<path>.*)$', 'serve'),
url(r'^media/(?P<path>.*)$', 'serve'),
)
Obviously these URL patterns will not work because we are serving files on "//s3.ama...". I thought in my wisdom that I could then write a piece of regex to get around the problem and tried replacing:
url(r'^static/(?P<path>.*)$', 'serve'),
with:
url(r'//s3.amazonaws.com/%s/static/(?P<path>.*)$' % settings.AWS_STORAGE_BUCKET_NAME, 'serve'),
This didn't work either. So to finally get around the problem I added a conditional statement in the settings file to decided where to serve static files from:
if DEBUG:
STATIC_URL = '/static/'
else:
STATIC_URL = '//s3.amazonaws.com/%s/static/' % AWS_STORAGE_BUCKET_NAME
What do people think of this solution? I'm not really happy with it going forwards. What are my alternatives?
The conditional in the settings is a good solution.
Another option is to use a separate settings file for local settings.

Django Admin CSS missing

I've been messing around with the new collectstatic command and have got it working for my normal pages. That is to say, I am able to load my css at this location http://localhost:8000/static/css/main.css. However, the css for my django admin doesn't seem to be showing up.
When I navigate to the admin css location at http://localhost:8000/static/admin/css/base.css, I'm getting a 404 page not found with the following error: /home/nai/GitProjects/cats/django-trunk/django/contrib/admin/media/css/base.css" does not exist. Looking in django-trunk, I never had the /home/nai/GitProjects/cats/django-trunk/django/contrib/admin/media/ folder to begin with.
Is that weird?
In any case, in my static folder, there is an admin folder with the accompanying css, img and js folders which was created when I ran collectstatic and the url of the base.css seems to be pointing to that location.
This is happening on my django development server. Here are some snippets to aid in the bug hunt:
urls
33 # In order for Dev Server to serve media files for the frontend site.
34 urlpatterns += staticfiles_urlpatterns()
35
36 try:
37 if settings.DEBUG: # defined in manage.py when the first arg is "runserver"
38 urlpatterns += patterns('',
39 (r'^media/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.MEDIA_ROOT}),
40 (r'^media-admin/(?P<path>.*)$', 'django.views.static.serve',{'document_root': os.path.join(settings.MEDIA_ROOT, '..', settings.ADMIN_MEDIA_PREFIX)}),
41 )
42 except NameError:
43 pass
I think it might be something to do with line 40 in my URLS file but changing media-admin to static/admin didnt help.
settings
58 ADMIN_MEDIA_PREFIX = '/static/admin'
69 STATIC_ROOT = os.path.join(os.path.abspath(os.path.join(PROJECT_ROOT, '..', MEDIA_DIR, 'static')), '')
70
71 # URL prefix for static files.
72 # Example: "http://media.lawrence.com/static/"
73 STATIC_URL = '/static/'
74
75 # Additional locations of static files. Global files are stored in here
76 STATICFILES_DIRS = (
77 os.path.join(os.path.abspath(os.path.join(PROJECT_ROOT, '..', 'proj_public', 'static', 'proj')), ''),
78 )
79
Django recommends that you deploy static files with a web server other than wsgi.
In settings.py, set:
STATIC_ROOT = 'static'
Run python manage.py collectstatic, which will copy the Django admin static files to /path/to/project/static/
Configure your static file server. If you use Nginx, you could add this config:
location /static/ {
alias /path/to/project/static/;
expires modified +1w;
}
Reload your web server
You should now have access to the static files.
In Django 1.4 ADMIN_MEDIA_PREFIX is deprecated. Here are the steps I followed to catch up with these somewhat recent Django changes:
in settings.py, add django.contrib.staticfiles to INSTALLED_APPS
in settings.py define STATIC_URL — the staticfiles app won't run without it. While using runserver they'll get handled magically, but when you deploy, this needs to be a location where those resources can be fetched by a browser.
I think that's all there was to it.
I'm using Django 1.4.3
What did NOT work for me:
No matter how much I edited ADMIN_MEDIA_PREFIX in settings.py I noticed no change in the HTML generated for the Django Admin pages. It always says /media/admin/base.css when I view the source.
What DID work for me.
Copied the 'admin' folder from /django/contrib/admin/static/ and pasted it into my projects 'media' folder
Now it works great.
It seems dumb, but I actually had this exact issue and the solution was to set DEBUG=False to DEBUG=True on my local dev environment. When debug is set to False, it thinks it's in a production environment which relies on a place to put static files, such as /var/www/html/static, whereas the debug set to True just uses the local directory.
Also make sure that AppDirectoriesFinder is not commented, happens when you're trying to customize your own app structure. Unfortunatelly it's pointless to seek such information in official docs.
STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]
just change one thing in settings.py
DEBUG = False # not working if you are not serve your static files for production.
just change
DEBUG = True
You need a trailing slash in your ADMIN_MEDIA_PREFIX setting.
Change to:
ADMIN_MEDIA_PREFIX = '/static/admin/'
I'm using chef to auto-build my django server on an AWS Ubuntu server. This post helped, but what I wound up doing was to add the directory to the package admin static pages in a local_setings.py:
https://github.com/jaycrossler/geoq-chef-repo/blob/master/cookbooks/geoq/templates/default/local_settings.py.erb#L16
(added to local_settings.py or to settings.py):
STATICFILES_DIRS = ('<%= node['geoq']['virtualenv']['location'] %>/local/lib/python2.7/site-packages/django/contrib/admin/static/',)
This resulted in local_settings.py having:
STATICFILES_DIRS = ('/var/lib/geoq/local/lib/python2.7/site-packages/django/contrib/admin/static/',)
Note, that if you have other items already in your STATICFILES_DIRS, you might want to append to the list, rather than overwriting it.
in my project, the solution is in settings.py, set:
DEBUG = False # debug false mod not working css
One solution might be to add your local IP to the ALLOWED_HOSTS list in settings.py
e.g.
CURRENT_IP = '192.168.0.123'
ALLOWED_HOSTS = ['127.0.0.1', 'localhost', '0.0.0.0', CURRENT_IP]
you need
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
I don't know how it was resolved, but I took these steps when I encountered the same problem. I simply add these line in settings.py.
ADMIN_MEDIA_PREFIX = '/static/admin/'
STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder','django.contrib.staticfiles.finders.AppDirectoriesFinder','compressor.finders.CompressorFinder', )
i hope this will help you all.
In settings.py
Don't use tuple for the
STATICFILES_DIRS =(
os.path.join(BASE_DIR, 'static'),
)
you should use list,like this
STATICFILES_DIRS =[
os.path.join(BASE_DIR, 'static'),
]

Django Admin has broken CSS link through apache, but works in runserver mode

For some reason, at some point the django administration got broken. The css is missing.
Here are my settings:
MEDIA_ROOT = os.path.normpath(os.path.join(SITE_ROOT, 'media/'))
MEDIA_URL = '/media/'
ADMIN_MEDIA_PREFIX = '/admin_media/'
However, the generated line on the admin page is still:
<link rel="stylesheet" type="text/css" href="/admin_media/css/base.css" />
but the site gives me 404 on this file.
And it gets better - if I use apache to view the project, that problem occurs. If I use python manage.py runserver the admin works well.
Any clues to why that might be happening?
- restarted apache, that didn't help.
here is what i have in the urls file:
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
Ok, I figured it out.
For production server, you have to setup a link to the setting you provided. For me, i chose admin_media folder, in the settings.py file:
ADMIN_MEDIA_PREFIX = '/admin_media/'
And in order to tell apache to look for files, you have to edit your sites-enabled file by adding the line:
Alias /admin_media/ /usr/lib/python2.6/dist-packages/django/contrib/admin/media/
Note though, that this is the path to the django contrib admin as installed on my server. Your server might have a different installation, so look up your settings. find out where your python is installed by copy pasting this in terminal:
python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
Good luck to everybody!