1 | =====================
|
---|
2 | Managing static files
|
---|
3 | =====================
|
---|
4 |
|
---|
5 | .. currentmodule:: django.contrib.staticfiles
|
---|
6 |
|
---|
7 | .. versionadded:: 1.3
|
---|
8 |
|
---|
9 | Django developers mostly concern themselves with the dynamic parts of web
|
---|
10 | applications -- the views and templates that render anew for each request. But
|
---|
11 | web applications have other parts: the static media files (images, CSS,
|
---|
12 | Javascript, etc.) that are needed to render a complete web page.
|
---|
13 |
|
---|
14 | For small projects, this isn't a big deal, because you can just keep the media
|
---|
15 | somewhere your web server can find it. However, in bigger projects -- especially
|
---|
16 | those comprised of multiple apps -- dealing with the multiple sets of static
|
---|
17 | files provided by each application starts to get tricky.
|
---|
18 |
|
---|
19 | That's what ``django.contrib.staticfiles`` is for: it collects media from each
|
---|
20 | of your applications (and any other places you specify) into a single location
|
---|
21 | that can easily be served in production.
|
---|
22 |
|
---|
23 | .. note::
|
---|
24 |
|
---|
25 | If you've used the `django-staticfiles`_ third-party app before, then
|
---|
26 | ``django.contrib.staticfiles`` will look very familiar. That's because
|
---|
27 | they're essentially the same code: ``django.contrib.staticfiles`` started
|
---|
28 | its life as `django-staticfiles`_ and was merged into Django 1.3.
|
---|
29 |
|
---|
30 | If you're upgrading from ``django-staticfiles``, please see `Upgrading from
|
---|
31 | django-staticfiles`_, below, for a few minor changes you'll need to make.
|
---|
32 |
|
---|
33 | .. _django-staticfiles: http://pypi.python.org/pypi/django-staticfiles/
|
---|
34 |
|
---|
35 | Using ``django.contrib.staticfiles``
|
---|
36 | ====================================
|
---|
37 |
|
---|
38 | Here's the basic usage in a nutshell:
|
---|
39 |
|
---|
40 | 1. Put your media somewhere that staticfiles will find it..
|
---|
41 |
|
---|
42 | Most of the time this place will be in a ``static`` directory within your
|
---|
43 | application, but it could also be a specific directory you've put into
|
---|
44 | your settings file. See the the documentation for the
|
---|
45 | :setting:`STATICFILES_DIRS` and :setting:`STATICFILES_FINDERS` settings
|
---|
46 | for details on where you can put media.
|
---|
47 |
|
---|
48 | 2. Add some ``staticfiles``-related settings to your settings file.
|
---|
49 |
|
---|
50 | First, you'll need to make sure that ``django.contrib.staticfiles`` is in
|
---|
51 | your :setting:`INSTALLED_APPS`.
|
---|
52 |
|
---|
53 | Next, you'll need to edit :setting:`STATICFILES_ROOT` to point to where
|
---|
54 | you'd like your static media stored. For example::
|
---|
55 |
|
---|
56 | STATICFILES_ROOT = "/home/jacob/projects/mysite.com/static_media"
|
---|
57 |
|
---|
58 | You may also want to set the :setting:`STATICFILES_URL` setting at this
|
---|
59 | time, though the default value (of ``/static/``) is perfect for local
|
---|
60 | development.
|
---|
61 |
|
---|
62 | There are a number of other options available that let you control *how*
|
---|
63 | media is stored, where ``staticfiles`` searches for files, and how files
|
---|
64 | will be served; see :ref:`the staticfiles settings reference
|
---|
65 | <staticfiles-settings>` for details.
|
---|
66 |
|
---|
67 | 3. Run the :djadmin:`collectstatic` management command::
|
---|
68 |
|
---|
69 | ./manage.py collectstatic
|
---|
70 |
|
---|
71 | This'll churn through your static file storage and move them into the
|
---|
72 | directory given by :setting:`STATICFILES_ROOT`.
|
---|
73 |
|
---|
74 | 4. Deploy that media.
|
---|
75 |
|
---|
76 | If you're using the built-in development server, you can quickly
|
---|
77 | serve static media locally by adding::
|
---|
78 |
|
---|
79 | from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
---|
80 | urlpatterns += staticfiles_urlpatterns()
|
---|
81 |
|
---|
82 | to the bottom of your URLconf. See :ref:`staticfiles-development` for
|
---|
83 | details.
|
---|
84 |
|
---|
85 | When it comes time to deploy to production, :ref:`staticfiles-production`
|
---|
86 | covers some common deployment strategies for static files.
|
---|
87 |
|
---|
88 | However you choose to deploy those files, you'll probably need to refer
|
---|
89 | to them in your templates. The easiest method is to use the included
|
---|
90 | context processor which will allow template code like:
|
---|
91 |
|
---|
92 | .. code-block:: html+django
|
---|
93 |
|
---|
94 | <img src="{{ STATICFILES_URL }}images/hi.jpg />
|
---|
95 |
|
---|
96 | See :ref:`staticfiles-in-templates` for more details, including an
|
---|
97 | alternate method (using a template tag).
|
---|
98 |
|
---|
99 | Those are the basics. For more details on common configuration options, read on;
|
---|
100 | for a detailed reference of the settings, commands, and other bits included with
|
---|
101 | the framework see :doc:`the staticfiles reference </ref/contrib/staticfiles>`.
|
---|
102 |
|
---|
103 | .. _staticfiles-in-templates:
|
---|
104 |
|
---|
105 | Referring to static files in templates
|
---|
106 | ======================================
|
---|
107 |
|
---|
108 | At some point, you'll probably need to link to static files in your templates.
|
---|
109 | You could, of course, simply hardcode the path to you assets in the templates:
|
---|
110 |
|
---|
111 | .. code-block:: html
|
---|
112 |
|
---|
113 | <img src="http://media.example.com/static/myimage.jpg" />
|
---|
114 |
|
---|
115 | Of course, there are some serious problems with this: it doesn't work well in
|
---|
116 | development, and it makes it *very* hard to change where you've deployed your
|
---|
117 | media. If, for example, you wanted to switch to using a content delivery network
|
---|
118 | (CDN), then you'd need to change more or less every single template.
|
---|
119 |
|
---|
120 | A far better way is to use the value of the :setting:`STATICFILES_URL` setting
|
---|
121 | directly in your templates. This means that a switch of media servers only
|
---|
122 | requires changing that single value. Much better!
|
---|
123 |
|
---|
124 | ``staticfiles`` inludes two built-in ways of getting at this setting in your
|
---|
125 | templates: a context processor and a template tag.
|
---|
126 |
|
---|
127 | With a context processor
|
---|
128 | ------------------------
|
---|
129 |
|
---|
130 | The included context processor is the easy way. Simply make sure
|
---|
131 | ``'django.contrib.staticfiles.context_processors.staticfiles'`` is in your
|
---|
132 | :setting:`TEMPLATE_CONTEXT_PROCESSORS`. It's there by default, and if you're
|
---|
133 | editing that setting by hand it should look something like::
|
---|
134 |
|
---|
135 | TEMPLATE_CONTEXT_PROCESSORS = (
|
---|
136 | 'django.core.context_processors.debug',
|
---|
137 | 'django.core.context_processors.i18n',
|
---|
138 | 'django.contrib.auth.context_processors.auth',
|
---|
139 | 'django.contrib.messages.context_processors.messages',
|
---|
140 | 'django.contrib.staticfiles.context_processors.staticfiles',
|
---|
141 | )
|
---|
142 |
|
---|
143 | Once that's done, you can refer to :setting:`STATICFILES_URL` in your templates:
|
---|
144 |
|
---|
145 | .. code-block:: html+django
|
---|
146 |
|
---|
147 | <img src="{{ STATICFILES_URL }}images/hi.jpg />
|
---|
148 |
|
---|
149 | If ``{{ STATICFILES_URL }}`` isn't working in your template, you're probably not
|
---|
150 | using :class:`~django.template.RequestContext` when rendering the template.
|
---|
151 |
|
---|
152 | As a brief refresher, context processors add variables into the contexts of
|
---|
153 | every template. However, context processors require that you use
|
---|
154 | :class:`~django.template.RequestContext` when rendering templates. This happens
|
---|
155 | automatically if you're using a :doc:`generic view </ref/class-based-views>`,
|
---|
156 | but in views written by hand you'll need to explicitally use ``RequestContext``
|
---|
157 | To see how that works, and to read more details, check out
|
---|
158 | :ref:`subclassing-context-requestcontext`.
|
---|
159 |
|
---|
160 | With a template tag
|
---|
161 | -------------------
|
---|
162 |
|
---|
163 | The second option is the :ttag:`get_staticfiles_prefix` template tag. You can
|
---|
164 | use this if you're not using :class:`~django.template.RequestContext`, or if you
|
---|
165 | need more control over exactly where and how :setting:`STATICFILES_URL` is
|
---|
166 | injected into the template. Here's an example:
|
---|
167 |
|
---|
168 | .. code-block:: html+django
|
---|
169 |
|
---|
170 | {% load staticfiles %}
|
---|
171 | <img src="{% get_staticfiles_prefix %}images/hi.jpg" />
|
---|
172 |
|
---|
173 | There's also a second form you can use to avoid extra processing if you need the
|
---|
174 | value multiple times:
|
---|
175 |
|
---|
176 | .. code-block:: html+django
|
---|
177 |
|
---|
178 | {% load staticfiles %}
|
---|
179 | {% get_staticfiles_prefix as STATIC_PREFIX %}
|
---|
180 |
|
---|
181 | <img src="{{ STATIC_PREFIX }}images/hi.jpg" />
|
---|
182 | <img src="{{ STATIC_PREFIX }}images/hi2.jpg" />
|
---|
183 |
|
---|
184 | .. _staticfiles-development:
|
---|
185 |
|
---|
186 | Serving static files in development
|
---|
187 | ===================================
|
---|
188 |
|
---|
189 | The static files tools are mostly designed to help with getting static media
|
---|
190 | successfully deployed into production. This usually means a separate, dedicated
|
---|
191 | media server, which is a lot of overhead to mess with when developing locally.
|
---|
192 | Thus, the ``staticfiles`` app ships with a quick and dirty helper view that you
|
---|
193 | can use to serve media locally in development.
|
---|
194 |
|
---|
195 | To enable this view, you'll add a couple of lines to your URLconf. The first
|
---|
196 | line goes at the top of the file, and the last line at the bottom::
|
---|
197 |
|
---|
198 | from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
---|
199 |
|
---|
200 | # ... the rest of your URLconf goes here ...
|
---|
201 |
|
---|
202 | urlpatterns += staticfiles_urlpatterns()
|
---|
203 |
|
---|
204 | This will inspect your :setting:`STATICFILES_URL` and
|
---|
205 | :setting:`STATICFILES_ROOT` settings and wire up the view to serve static media
|
---|
206 | accordingly. Remember to run :djadmin:`collectstatic` when your media changes;
|
---|
207 | the view only serves static files that have been collected.
|
---|
208 |
|
---|
209 | .. warning::
|
---|
210 |
|
---|
211 | This will only work if :setting:`DEBUG` is ``True``.
|
---|
212 |
|
---|
213 | That's because this view is **grossly inefficient** and probably
|
---|
214 | **insecure**. This is only intended for local development, and should
|
---|
215 | **never be used in production**.
|
---|
216 |
|
---|
217 | For a few more details, including an alternate method of enabling this view,
|
---|
218 | see :ref:`staticfiles-development-view`.
|
---|
219 |
|
---|
220 | .. _staticfiles-production:
|
---|
221 |
|
---|
222 | Serving static files in production
|
---|
223 | ==================================
|
---|
224 |
|
---|
225 | The basic outline of putting static files into production a simple: run the
|
---|
226 | :djadmin:`collectstatic` command when static media changes, then arrange for the
|
---|
227 | collected media directory (:setting:`STATICFILES_ROOT`) to be moved to the media
|
---|
228 | server and served.
|
---|
229 |
|
---|
230 | Of course, as with all deployment tasks, the devil's in the details. Every
|
---|
231 | production setup will be a bit different, so you'll need to adapt the basic
|
---|
232 | outline to fit your needs. Below are a few common patterns that might help.
|
---|
233 |
|
---|
234 | Serving the app and your static files from the same server
|
---|
235 | ----------------------------------------------------------
|
---|
236 |
|
---|
237 | If you want to serve your media from the same server that's already serving your
|
---|
238 | app, the basic outline gets modified to look something like:
|
---|
239 |
|
---|
240 | * Push your code up to the deployment server.
|
---|
241 | * On the server, run :djadmin:`collectmedia` to move all the media into
|
---|
242 | :setting:`STATICFILES_ROOT`.
|
---|
243 | * Point your web server at :setting:`STATICFILES_ROOT`. For example, here's
|
---|
244 | of :ref:`how to do this under Apache and mod_wsgi <serving-media-files>`.
|
---|
245 |
|
---|
246 | You'll probably want to automate this process, especially if you've got multiple
|
---|
247 | web servers. There's any number of ways to do this automation, but one option
|
---|
248 | that many Django developers enjoy is `Fabric`__.
|
---|
249 |
|
---|
250 | __ http://fabfile.org/
|
---|
251 |
|
---|
252 | Below, and in the following sections, we'll show off a few example fabfiles
|
---|
253 | (i.e. Fabric scripts) that automate these media deployment options. The syntax
|
---|
254 | of a fabfile is fairly streightforward but won't be covered here; consult `Fabric's documentation`__, for a complete explanation of the syntax..
|
---|
255 |
|
---|
256 | __ http://docs.fabfile.org/
|
---|
257 |
|
---|
258 | So, a fabfile to deploy media to a couple of web servers might look something
|
---|
259 | like::
|
---|
260 |
|
---|
261 | from fabric.api import *
|
---|
262 |
|
---|
263 | # Hosts to deploy onto
|
---|
264 | env.hosts = ['www1.example.com', 'www2.example.com']
|
---|
265 |
|
---|
266 | # Where your project code lives on the server
|
---|
267 | env.project_root = '/home/www/myproject'
|
---|
268 |
|
---|
269 | def deploy_static():
|
---|
270 | with cd(env.project_root):
|
---|
271 | run('./manage.py collectstatic')
|
---|
272 |
|
---|
273 | Serving static files from a dedicated media server
|
---|
274 | --------------------------------------------------
|
---|
275 |
|
---|
276 | Most larger Django apps use a separate Web server -- i.e., one that's not also
|
---|
277 | running Django -- for serving media. This server often runs a different type of
|
---|
278 | web server -- faster but less full-featured. Some good choices are:
|
---|
279 |
|
---|
280 | * lighttpd_
|
---|
281 | * Nginx_
|
---|
282 | * TUX_
|
---|
283 | * Cherokee_
|
---|
284 | * A stripped-down version of Apache_
|
---|
285 |
|
---|
286 | .. _lighttpd: http://www.lighttpd.net/
|
---|
287 | .. _Nginx: http://wiki.nginx.org/Main
|
---|
288 | .. _TUX: http://en.wikipedia.org/wiki/TUX_web_server
|
---|
289 | .. _Apache: http://httpd.apache.org/
|
---|
290 | .. _Cherokee: http://www.cherokee-project.com/
|
---|
291 |
|
---|
292 | Configuring these servers is out of scope of this document; check each server's
|
---|
293 | respective documentation for instructions.
|
---|
294 |
|
---|
295 | Since your media server won't be running Django, you'll need to modify the
|
---|
296 | deployment strategy to look something like:
|
---|
297 |
|
---|
298 | * When your media changes, run :djadmin:`collectstatic` locally.
|
---|
299 | * Push your local :setting:`STATICFILES_ROOT` up to the media server
|
---|
300 | into the directory that's being served. ``rsync`` is a good
|
---|
301 | choice for this step since it only needs to transfer the
|
---|
302 | bits of static media that have changed.
|
---|
303 |
|
---|
304 | Here's how this might look in a fabfile::
|
---|
305 |
|
---|
306 | from fabric.api import *
|
---|
307 | from fabric.contrib import project
|
---|
308 |
|
---|
309 | # Where the static files get collected locally
|
---|
310 | env.local_static_root = '/tmp/static'
|
---|
311 |
|
---|
312 | # Where the static files should go remotely
|
---|
313 | env.remote_static_root = '/home/www/media.example.com'
|
---|
314 |
|
---|
315 | @roles('media')
|
---|
316 | def deploy_static():
|
---|
317 | local('./manage.py collectstatic')
|
---|
318 | project.rysnc_project(
|
---|
319 | remote_dir = env.remote_static_root,
|
---|
320 | local_dir = env.local_static_root,
|
---|
321 | delete = True
|
---|
322 | )
|
---|
323 |
|
---|
324 | .. _staticfiles-from-cdn:
|
---|
325 |
|
---|
326 | Serving static media from a cloud service or CDN
|
---|
327 | ------------------------------------------------
|
---|
328 |
|
---|
329 | Another common tactic is to serve media from a cloud storage provider like
|
---|
330 | Amazon's S3__ and/or a CDN (content delivery network). This lets you ignore the
|
---|
331 | problems of serving media, and can often make for faster-loading webpages
|
---|
332 | (especially when using a CDN).
|
---|
333 |
|
---|
334 | When using these services, the basic workflow would look a bit like the above,
|
---|
335 | except that instead of using ``rsync`` to transfer your media to the server
|
---|
336 | you'd need to transfer the media to the storage provider or CDN.
|
---|
337 |
|
---|
338 | There's any number of ways you might do this, but if the provider has an API a
|
---|
339 | :doc:`custom file storage backend </howto/custom-file-storage>` will make the
|
---|
340 | process incredibly simple. If you've written or are using a 3rd party custom
|
---|
341 | storage backend, you can tell :djadmin:`collectstatic` to use it by setting
|
---|
342 | :setting:`STATICFILES_STORAGE` to the storage engine.
|
---|
343 |
|
---|
344 | For example, if you've written an S3 storage backend in
|
---|
345 | ``myproject.storage.S3Storage`` you could use it with::
|
---|
346 |
|
---|
347 | STATICFILES_STORAGE = 'storages.backends.s3.S3Storage'
|
---|
348 |
|
---|
349 | Once that's done, all you have to do is run :djadmin:`collectstatic` and your
|
---|
350 | media would be pushed through your storage package up to S3. If you later needed
|
---|
351 | to swich to a different storage provider, it could be as simple as changing your
|
---|
352 | :setting:`STATICFILES_STORAGE` setting.
|
---|
353 |
|
---|
354 | For details on how you'd write one of these backends,
|
---|
355 | :doc:`/howto/custom-file-storage`.
|
---|
356 |
|
---|
357 | .. seealso::
|
---|
358 |
|
---|
359 | The `django-storages`__ project is a 3rd party app that provides many
|
---|
360 | storage backends for many common file storage APIs (including S3).
|
---|
361 |
|
---|
362 | __ http://s3.amazonaws.com/
|
---|
363 | __ http://code.welldev.org/django-storages/wiki/S3Storage
|
---|
364 |
|
---|
365 | Upgrading from ``django-staticfiles``
|
---|
366 | =====================================
|
---|
367 |
|
---|
368 | ``django.contrib.staticfiles`` began its life as `django-staticfiles`_. If
|
---|
369 | you're upgrading from `django-staticfiles`_ to ``django.contrib.staticfiles``,
|
---|
370 | you'll need to make a few changes:
|
---|
371 |
|
---|
372 | * Application files should now live in a ``static`` directory in each app
|
---|
373 | (`django-staticfiles`_ used the name ``media``, which was slightly
|
---|
374 | confusing).
|
---|
375 |
|
---|
376 | * The management commands ``build_static`` and ``resolve_static`` are now
|
---|
377 | called :djadmin:`collectstatic` and :djadmin:`findstatic`.
|
---|
378 |
|
---|
379 | * The settings ``STATIC_URL`` and ``STATIC_ROOT`` were renamed to
|
---|
380 | :setting:`STATICFILES_URL` and :setting:`STATICFILES_ROOT`.
|
---|
381 |
|
---|
382 | * The settings ``STATICFILES_PREPEND_LABEL_APPS``,
|
---|
383 | ``STATICFILES_MEDIA_DIRNAMES`` and ``STATICFILES_EXCLUDED_APPS`` were
|
---|
384 | removed.
|
---|
385 |
|
---|
386 | * The setting ``STATICFILES_RESOLVERS`` was removed, and replaced by the new
|
---|
387 | :setting:`STATICFILES_FINDERS`.
|
---|
388 |
|
---|
389 | * The default for :setting:`STATICFILES_STORAGE` was renamed from
|
---|
390 | ``staticfiles.storage.StaticFileStorage`` to
|
---|
391 | ``staticfiles.storage.StaticFilesStorage``
|
---|
392 |
|
---|
393 | Learn more
|
---|
394 | ==========
|
---|
395 |
|
---|
396 | This document has covered the basics and some common usage patterns. For
|
---|
397 | complete details on all the settings, commands, template tags, and other pieces
|
---|
398 | include in ``django.contrib.staticfiles``, see :doc:`the statcfiles reference
|
---|
399 | </ref/contrib/staticfiles>`.
|
---|