As stated in topic, my Django site media url is returning 404 after trying to access it. Everything was working flawless until I wanted to end the development process and set
DEBUG = True
in settings.py to have the site finished once and for all. When I change DEBUG back to
DEBUG = False
it works fine once again. I have no idea what's the problem, any suggestions?
This is by design: https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-during-development
If you use django.contrib.staticfiles as explained above, runserver will do this automatically when DEBUG is set to True.
That being said, you can use the following workaround by modifying your urls.py:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = patterns('',
# ... the rest of your URLconf goes here ...
) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Note that this is highly inefficient and not encouraged for production use. You should normally configure your web server (apache, nginx, etc) to serve your static and media content.
Related
I understand the concept of what I want to do (there is a rather nice question here: Django, REST and Angular Routes)
Django has a route for DRF, Admin, and needs at least one more, for the angular page.
But I'm not sure on the implementation details, particularly in where to put the frontend/static files, what to put in urls.py, and how to configure it for dev+production.
My url patterns currently look like this:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
Ideally, in production, I want serve the HTML without touching django - straight from nginx or similar (probably using AWS EB, but that is outside the scope of this question).
For Dev - I don't mind, as long as it works!
Skipping djangos templating system for angular would be great, rather than altering angulars operators. I don't intend to use django templates (except in djangos admin, and DRFs browsable views)
For development, I use something like this, at then end of the main urls.py file, to serve static files from various directories:
if settings.DEBUG:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf.urls.static import static
# this connects STATIC_URL to STATIC_ROOT
urlpatterns += staticfiles_urlpatterns()
# connect other paths to directories
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
urlpatterns += static('/app/',
document_root=join(settings.BASE_DIR, '../ng_app/'))
For production, you set the webserver to handle the requests. First the known routes like /admin/, /api/, /api-auth/ and files in /static/.
And then a catch-all route / that would always serve your index.html with the Angular app for any route. So that HTML5 routes in Angular will always load the app first, and the app then uses its own routes to build the correct page from API data.
The actual app files could be anywhere, even on a different server.
Community,
I am using Django 1.7. Due to specific nature of the project, I have complicated needs for handling static files. In other words, I need /static/ to be served on development just as usual, but /static/blueprints/ subdirectory should be served by a custom view.
It seems anyway that static serving view has priority above everything in urls.py. The following just does not work:
urlpatterns = patterns('',
url(r'^static/blueprints/(?P<blueprint>[\w-]+)/(?P<path>.+)', 'my_view_name'),
...
)
The view never gets fired when accessing an appropriate URL. But changing static/blueprints to, say, my_static/blueprints makes this path to work, so the view actually does work.
Of course, I need that only on development; on production, a script will be used to form the necessary directory structure served by Nginx. So solutions:
Avoid using debug=True on devserver. But Django's debugger is very useful.
Avoid using django.contrib.staticfiles. Not pleasing too, I'd like to use the collectstaic command.
Use just /blueprints/ path instead of /static/blueprints/, which is a solution, but just against aesthetics.
Is there any more elegant solution?
You're using ./manage.py runserver on your dev server, right? Then you can go this way: ./manage.py runserver --nostatic, and in urls.py:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns = patterns('',
url(r'^static/blueprints/(?P<blueprint>[\w-]+)/(?P<path>.+)', 'my_view_name'),
...
)
if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns()
I'm using http://appfog.com I have DEBUG = True and ADMIN_MEDIA_PREFIX = '/static/admin/'
The css for the admin is missing.
Django only serves static files if DEBUG=True and it is running the development server.
Documentation:
This view is automatically enabled and will serve your static files at STATIC_URL when you use the built-in runserver management command
[...]
To enable this view if you are using some other server for local development, you'll add a couple of lines to your URLconf. The first line goes at the top of the file, and the last line at the bottom.
Example:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
# ... the rest of your URLconf goes here ...
urlpatterns += staticfiles_urlpatterns()
Hope this helps
Using dbieber's Django template for appfog this is the approach that worked for me:
Create a directory for static files in your project directory, then set up a URL to have the appfog server serve these files:
cd <project>
mkdir static
In urls.py, make sure the urlpattern is set to include static files (this is already there if you use the template):
urlpatterns += patterns('',
...
url(r'^static/(?P<path>.*)$',
'django.views.static.serve',
{'document_root': settings.STATIC_ROOT),
)
Collect all static files into the static directory
python manage.py collectstatic
Deploy to appfog
af update <appname>
I'm using the staticfiles app during development, which doesn't work unless DEBUG is turned on.
From the docs:
Warning This will only work if DEBUG is True.
That's because this view is grossly inefficient and probably insecure.
This is only intended for local development, and should never be used
in production.
Additionally, when using staticfiles_urlpatterns your STATIC_URL
setting can't be empty or a full URL, such as
http://static.example.com/.
I'm trying to view my Http404 templates, though, and of course they don't work in DEBUG mode. So I'm in a catch 22 - if I want to view the 404 page I have to turn off DEBUG, but then no static files are servers and I can't see any images, etc.
You can simply pretend you are in production. Run:
python manage.py collectstatic --noinput
To have all your files copied to STATIC_ROOT. Then, temporarily add the following to urls.py:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
)
You'll have to run collectstatic each time you make a change to any static files, so I would suggest live-editing in something like Firebug and then saving the finished product. Also, remember to delete the static directory and remove that line from urls.py when you're done.
I haven't tried it myself, but you might try setting DEBUG_PROPAGATE_EXCEPTIONS = True
https://docs.djangoproject.com/en/dev/ref/settings/
When I was using the built-in simple server, everything is OK, the admin interface is beautiful:
python manage.py runserver
However, when I try to serve my application using a wsgi server with django.core.handlers.wsgi.WSGIHandler, Django seems to forget where the admin media files is, and the admin page is not styled at all:
gunicorn_django
How did this happen?
When I look into the source code of Django, I find out the reason.
Somewhere in the django.core.management.commands.runserver module, a WSGIHandler object is
wrapped inside an AdminMediaHandler.
According to the document, AdminMediaHandler is a
WSGI middleware that intercepts calls
to the admin media directory, as
defined by the ADMIN_MEDIA_PREFIX setting, and serves those images.
Use this ONLY LOCALLY, for development! This hasn't been tested
for
security and is not super efficient.
And that's why the admin media files can only be found automatically when I was using the test server.
Now I just go ahead and set up the admin media url mapping manually :)
Django by default doesn't serve the media files since it usually is better to serve these static files on another server (for performance etc.). So, when deploying your application you have to make sure you setup another server (or virtual server) which serves the media (including the admin media). You can find the admin media in django/contrib/admin/media. You should setup your MEDIA_URL and ADMIN_MEDIA_URL so that they point to the media files. See also http://docs.djangoproject.com/en/dev/howto/static-files/#howto-static-files.
I've run into this problem too (because I do some development against gunicorn), and here's how to remove the admin-media magic and serve admin media like any other media through urls.py:
import os
import django
...
admin_media_url = settings.ADMIN_MEDIA_PREFIX.lstrip('/') + '(?P<path>.*)$'
admin_media_path = os.path.join(django.__path__[0], 'contrib', 'admin', 'media')
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^' + admin_media_url , 'django.views.static.serve', {
'document_root': admin_media_path,
}, name='admin-media'),
...
)
Also: http://djangosnippets.org/snippets/2547/
And, of course, #include <production_disclaimer.h>.