Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should Django Apps bundle static media?

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,

like image 915
Edan Maor Avatar asked Jan 14 '10 12:01

Edan Maor


People also ask

How does Django load static files?

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.

How does Django manage static files in production?

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.


3 Answers

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."

like image 54
Carl Meyer Avatar answered Oct 24 '22 09:10

Carl Meyer


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.

like image 25
Dominic Rodger Avatar answered Oct 24 '22 09:10

Dominic Rodger


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

like image 2
jujule Avatar answered Oct 24 '22 07:10

jujule