Background:
I'm starting to use Django for the first time, which is also my first foray into web development. I just got stuck on the whole "serving static media" problem. After spending a while looking at all the documentation and StackOverflow questions, I think I understand how it's supposed to work (i.e. MEDIA_ROOT, MEDIA_URL, updating the urls file, etc).
My Question:
Ok, so here's the part I'm not sure about. Django applications are supposed to be "pluggable", i.e. I can move an application from one project to another. So, how should these applications bundle static media?
For example, let's say I have a "foo" application, which has templates that load some css/image files. Where am I supposed to put these files, so that they'll automatically get served once I include the application?
The only solution I see, is that installing an application has to include the extra step of copying its static media to some place on your own server that serves that media.
Is this the accepted way to do it? It includes an extra step, but maybe that's standard when dealing with web-dev (I'm new so I don't really know).
Also, if this is the way, is there a standard way to collect all my static media to make it easy to know what I need to serve? (I.e., is it standard to have a folder named "media" or something inside the app?).
Thanks,
Using the collectstatic command, Django looks for all static files in your apps and collects them wherever you told it to, i.e. the STATIC_ROOT . In our case, we are telling Django that when we run python manage.py collectstatic , gather all static files into a folder called staticfiles in our project root directory.
The basic outline of putting static files into production consists of two steps: run the collectstatic command when static files change, then arrange for the collected static files directory ( STATIC_ROOT ) to be moved to the static file server and served.
Convention is to put static media in either media/appname/ or static/appname/ within the app (similar to templates).
For using apps in your project that come with media, I strongly recommend using django-staticfiles. It will automatically serve media (including media within apps) in development through a view that replaces django.views.static.serve, and it comes with a build_static management command that will copy media from all apps into a single directory for serving in production.
Update: django-staticfiles has become part of Django 1.3. It now expects app media to live in a "static/" subdirectory of the app, not "media/". And the management command is now "collectstatic."
The only app I know of that deals with this without any intervention is the rather wonderful django-debug-toolbar, though it's arguable that this isn't a great example, since it's an app specifically designed for debug mode only.
The way it deals with it is that it serves its media through Django itself - see the source for urls.py:
url(r'^%s/m/(.*)$' % _PREFIX, 'debug_toolbar.views.debug_media'),
In general, this is a bad idea (you don't want to serve static files through Django), per this comment from the documentation:
[Serving static files through Django] is inefficient and insecure. Do not use this in a production setting. Use this only for development.
Obviously, the django-debug-toolbar is only used for development, so I think its method of deployment makes sense, but this is very much an exception.
In general, the best way I know to do it is to create symbolic links wherever your media is stored to the media inside your app code. For example, create a folder called media
within your app, and then require users installing your app to either add a symbolic link from their media directory, or copy the whole thing.
i usually put apps media in ./apps/appname/static (my apps resides in an apps subfolder)
then i have something similar in the vhost in apache :
AliasMatch ^/apps/([^/]+)/static/(.*) /home/django/projectname/apps/$1/static/$2
<DirectoryMatch "^/home/django/projectname/apps/([^/]+)/static/*">
Order deny,allow
Options -Indexes
deny from all
Options +FollowSymLinks
<FilesMatch "\.(flv|gif|jpg|jpeg|png|ico|swf|js|css|pdf|txt|htm|html|json)$">
allow from all
</FilesMatch>
</DirectoryMatch>
i also have this in my urls.py for dev server (use only for debug) :
def statics_wrapper(request, **dict):
from django.views import static
return static.serve(request, dict['path'], document_root = os.path.join(settings.BASE_DIR, 'apps', dict['app'], 'static'), show_indexes=True)
urlpatterns += patterns('', (r'^apps/(?P<app>[^/]+)/static/(?P<path>.+)$', statics_wrapper))
this is very handy because statics url are simply mapped to filesystem, eg :
http://wwww.ecample.com/apps/calendar/static/js/calendar.js resides in [BASE_DIR]/apps/calendar/static/js/calendar.js
hope this helps
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