views:

148

answers:

3

Hi all,

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,

+2  A: 

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.

Dominic Rodger
And how should I avoid naming clashes/refer to it in my code? If I have, say, a "foo" app with a media folder and a "bar" app with a media folder, then how do I refer to the folder inside the application templates, without causing problems?
Edan Maor
If your app is called `foobar`, then refer to your media using `{{ MEDIA_URL }}foobar/myawesomejs.js`. Require your users to setup the symlink at `foobar` within their media directory.
Dominic Rodger
I think my answer below (using django-staticfiles) is a better all-around solution; especially since it looks like something based on staticfiles may be included directly in Django 1.3.
Carl Meyer
@Carl - have you got a source for your Django 1.3 comment? Not doubting you - just struggling to find an overview of what's coming in 1.3, which I'd be interested in.
Dominic Rodger
@Dominic - see this django-developers thread: http://groups.google.com/group/django-developers/browse_thread/thread/b333c14f40acd22a/288a34cc41bb4395 and the work begun here by a Django core dev (and author of django-staticfiles): http://github.com/jezdez/django/tree/staticfiles
Carl Meyer
@Dominic - at this early stage in the process there is no overview of what's coming in 1.3, as the target feature list hasn't been put together yet. To get some idea of what's likely, you have to follow the django-developers mailing list.
Carl Meyer
@Carl - thanks!
Dominic Rodger
+1  A: 

Hi

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

jujule
+2  A: 

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.

Carl Meyer