431 lines
17 KiB
Plaintext
431 lines
17 KiB
Plaintext
=====================
|
|
Managing static files
|
|
=====================
|
|
|
|
.. currentmodule:: django.contrib.staticfiles
|
|
|
|
.. versionadded:: 1.3
|
|
|
|
Django developers mostly concern themselves with the dynamic parts of web
|
|
applications -- the views and templates that render anew for each request. But
|
|
web applications have other parts: the static media files (images, CSS,
|
|
Javascript, etc.) that are needed to render a complete web page.
|
|
|
|
For small projects, this isn't a big deal, because you can just keep the media
|
|
somewhere your web server can find it. However, in bigger projects -- especially
|
|
those comprised of multiple apps -- dealing with the multiple sets of static
|
|
files provided by each application starts to get tricky.
|
|
|
|
That's what ``django.contrib.staticfiles`` is for: it collects media from each
|
|
of your applications (and any other places you specify) into a single location
|
|
that can easily be served in production.
|
|
|
|
.. note::
|
|
|
|
If you've used the `django-staticfiles`_ third-party app before, then
|
|
``django.contrib.staticfiles`` will look very familiar. That's because
|
|
they're essentially the same code: ``django.contrib.staticfiles`` started
|
|
its life as `django-staticfiles`_ and was merged into Django 1.3.
|
|
|
|
If you're upgrading from ``django-staticfiles``, please see `Upgrading from
|
|
django-staticfiles`_, below, for a few minor changes you'll need to make.
|
|
|
|
.. _django-staticfiles: http://pypi.python.org/pypi/django-staticfiles/
|
|
|
|
Using ``django.contrib.staticfiles``
|
|
====================================
|
|
|
|
Here's the basic usage in a nutshell:
|
|
|
|
1. Put your media somewhere that staticfiles will find it.
|
|
|
|
Most of the time this place will be in a ``static`` directory within your
|
|
application, but it could also be a specific directory you've put into
|
|
your settings file. See the the documentation for the
|
|
:setting:`STATICFILES_DIRS` and :setting:`STATICFILES_FINDERS` settings
|
|
for details on where you can put media.
|
|
|
|
2. Add some ``staticfiles``-related settings to your settings file.
|
|
|
|
First, you'll need to make sure that ``django.contrib.staticfiles`` is in
|
|
your :setting:`INSTALLED_APPS`.
|
|
|
|
Next, you'll need to edit :setting:`STATIC_ROOT` to point to where
|
|
you'd like your static media stored. For example::
|
|
|
|
STATIC_ROOT = "/home/jacob/projects/mysite.com/static_media"
|
|
|
|
You may also want to set the :setting:`STATIC_URL` setting at this
|
|
time, though the default value (of ``/static/``) is perfect for local
|
|
development.
|
|
|
|
There are a number of other options available that let you control *how*
|
|
media is stored, where ``staticfiles`` searches for files, and how files
|
|
will be served; see :ref:`the staticfiles settings reference
|
|
<staticfiles-settings>` for details.
|
|
|
|
3. Run the :djadmin:`collectstatic` management command::
|
|
|
|
./manage.py collectstatic
|
|
|
|
This'll churn through your static file storage and move them into the
|
|
directory given by :setting:`STATIC_ROOT`. (This is not necessary
|
|
in local development if you are using :djadmin:`runserver` or adding
|
|
``staticfiles_urlpatterns`` to your URLconf; see below).
|
|
|
|
4. Deploy that media.
|
|
|
|
If you're using the built-in development server (the
|
|
:djadmin:`runserver` management command) and have the :setting:`DEBUG`
|
|
setting set to ``True``, your staticfiles will automatically be served
|
|
from :setting:`STATIC_URL` in development.
|
|
|
|
If you are using some other server for local development, you can
|
|
quickly serve static media locally by adding::
|
|
|
|
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
|
urlpatterns += staticfiles_urlpatterns()
|
|
|
|
to the bottom of your URLconf. See :ref:`staticfiles-development` for
|
|
details.
|
|
|
|
When it comes time to deploy to production, :ref:`staticfiles-production`
|
|
covers some common deployment strategies for static files.
|
|
|
|
However you choose to deploy those files, you'll probably need to refer
|
|
to them in your templates. The easiest method is to use the included
|
|
context processor which will allow template code like:
|
|
|
|
.. code-block:: html+django
|
|
|
|
<img src="{{ STATIC_URL }}images/hi.jpg />
|
|
|
|
See :ref:`staticfiles-in-templates` for more details, including an
|
|
alternate method (using a template tag).
|
|
|
|
Those are the basics. For more details on common configuration options, read on;
|
|
for a detailed reference of the settings, commands, and other bits included with
|
|
the framework see :doc:`the staticfiles reference </ref/contrib/staticfiles>`.
|
|
|
|
.. note::
|
|
|
|
In previous versions of Django, it was common to place static assets in
|
|
:setting:`MEDIA_ROOT` along with user-uploaded files, and serve them both at
|
|
:setting:`MEDIA_URL`. Part of the purpose of introducing the ``staticfiles``
|
|
app is to make it easier to keep static files separate from user-uploaded
|
|
files. For this reason, you will probably want to make your
|
|
:setting:`MEDIA_ROOT` and :setting:`MEDIA_URL` different from your
|
|
:setting:`STATIC_ROOT` and :setting:`STATIC_URL`. You will need to
|
|
arrange for serving of files in :setting:`MEDIA_ROOT` yourself;
|
|
``staticfiles`` does not deal with user-uploaded media at all.
|
|
|
|
.. _staticfiles-in-templates:
|
|
|
|
Referring to static files in templates
|
|
======================================
|
|
|
|
At some point, you'll probably need to link to static files in your templates.
|
|
You could, of course, simply hardcode the path to you assets in the templates:
|
|
|
|
.. code-block:: html
|
|
|
|
<img src="http://media.example.com/static/myimage.jpg" />
|
|
|
|
Of course, there are some serious problems with this: it doesn't work well in
|
|
development, and it makes it *very* hard to change where you've deployed your
|
|
media. If, for example, you wanted to switch to using a content delivery network
|
|
(CDN), then you'd need to change more or less every single template.
|
|
|
|
A far better way is to use the value of the :setting:`STATIC_URL` setting
|
|
directly in your templates. This means that a switch of media servers only
|
|
requires changing that single value. Much better!
|
|
|
|
``staticfiles`` inludes two built-in ways of getting at this setting in your
|
|
templates: a context processor and a template tag.
|
|
|
|
With a context processor
|
|
------------------------
|
|
|
|
The included context processor is the easy way. Simply make sure
|
|
``'django.core.context_processors.static'`` is in your
|
|
:setting:`TEMPLATE_CONTEXT_PROCESSORS`. It's there by default, and if you're
|
|
editing that setting by hand it should look something like::
|
|
|
|
TEMPLATE_CONTEXT_PROCESSORS = (
|
|
'django.core.context_processors.debug',
|
|
'django.core.context_processors.i18n',
|
|
'django.core.context_processors.media',
|
|
'django.core.context_processors.static',
|
|
'django.contrib.auth.context_processors.auth',
|
|
'django.contrib.messages.context_processors.messages',
|
|
)
|
|
|
|
Once that's done, you can refer to :setting:`STATIC_URL` in your templates:
|
|
|
|
.. code-block:: html+django
|
|
|
|
<img src="{{ STATIC_URL }}images/hi.jpg />
|
|
|
|
If ``{{ STATIC_URL }}`` isn't working in your template, you're probably not
|
|
using :class:`~django.template.RequestContext` when rendering the template.
|
|
|
|
As a brief refresher, context processors add variables into the contexts of
|
|
every template. However, context processors require that you use
|
|
:class:`~django.template.RequestContext` when rendering templates. This happens
|
|
automatically if you're using a :doc:`generic view </ref/class-based-views>`,
|
|
but in views written by hand you'll need to explicitally use ``RequestContext``
|
|
To see how that works, and to read more details, check out
|
|
:ref:`subclassing-context-requestcontext`.
|
|
|
|
With a template tag
|
|
-------------------
|
|
|
|
The second option is the :ttag:`get_static_prefix` template tag. You can
|
|
use this if you're not using :class:`~django.template.RequestContext`, or if you
|
|
need more control over exactly where and how :setting:`STATIC_URL` is
|
|
injected into the template. Here's an example:
|
|
|
|
.. code-block:: html+django
|
|
|
|
{% load static %}
|
|
<img src="{% get_static_prefix %}images/hi.jpg" />
|
|
|
|
There's also a second form you can use to avoid extra processing if you need the
|
|
value multiple times:
|
|
|
|
.. code-block:: html+django
|
|
|
|
{% load static %}
|
|
{% get_static_prefix as STATIC_PREFIX %}
|
|
|
|
<img src="{{ STATIC_PREFIX }}images/hi.jpg" />
|
|
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" />
|
|
|
|
.. _staticfiles-development:
|
|
|
|
Serving static files in development
|
|
===================================
|
|
|
|
The static files tools are mostly designed to help with getting static media
|
|
successfully deployed into production. This usually means a separate, dedicated
|
|
media server, which is a lot of overhead to mess with when developing locally.
|
|
Thus, the ``staticfiles`` app ships with a quick and dirty helper view that you
|
|
can use to serve files locally in development.
|
|
|
|
This view is automatically enabled and will serve your static files at
|
|
:setting:`STATIC_URL` when you use the built-in :djadmin:`runserver`.
|
|
|
|
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::
|
|
|
|
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
|
|
|
# ... the rest of your URLconf goes here ...
|
|
|
|
urlpatterns += staticfiles_urlpatterns()
|
|
|
|
This will inspect your :setting:`STATIC_URL` and
|
|
:setting:`STATIC_ROOT` settings and wire up the view to serve static media
|
|
accordingly. Don't forget to set the :setting:`STATICFILES_DIRS` setting
|
|
appropriately to let ``django.contrib.staticfiles`` know where to look for
|
|
(additional) files.
|
|
|
|
.. warning::
|
|
|
|
This will only work if :setting:`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, your :setting:`STATIC_URL` setting can't be either empty
|
|
or a full URL such as ``http://static.example.com/``.
|
|
|
|
For a few more details, including an alternate method of enabling this view,
|
|
see :ref:`staticfiles-development-view`.
|
|
|
|
.. _staticfiles-production:
|
|
|
|
Serving static files in production
|
|
==================================
|
|
|
|
The basic outline of putting static files into production is simple: run the
|
|
:djadmin:`collectstatic` command when static media changes, then arrange for the
|
|
collected media directory (:setting:`STATIC_ROOT`) to be moved to the media
|
|
server and served.
|
|
|
|
Of course, as with all deployment tasks, the devil's in the details. Every
|
|
production setup will be a bit different, so you'll need to adapt the basic
|
|
outline to fit your needs. Below are a few common patterns that might help.
|
|
|
|
Serving the app and your static files from the same server
|
|
----------------------------------------------------------
|
|
|
|
If you want to serve your media from the same server that's already serving your
|
|
app, the basic outline gets modified to look something like:
|
|
|
|
* Push your code up to the deployment server.
|
|
* On the server, run :djadmin:`collectstatic` to move all the media into
|
|
:setting:`STATIC_ROOT`.
|
|
* Point your web server at :setting:`STATIC_ROOT`. For example, here's
|
|
:ref:`how to do this under Apache and mod_wsgi <serving-media-files>`.
|
|
|
|
You'll probably want to automate this process, especially if you've got multiple
|
|
web servers. There's any number of ways to do this automation, but one option
|
|
that many Django developers enjoy is `Fabric`__.
|
|
|
|
__ http://fabfile.org/
|
|
|
|
Below, and in the following sections, we'll show off a few example fabfiles
|
|
(i.e. Fabric scripts) that automate these media deployment options. The syntax
|
|
of a fabfile is fairly straightforward but won't be covered here; consult
|
|
`Fabric's documentation`__, for a complete explanation of the syntax..
|
|
|
|
__ http://docs.fabfile.org/
|
|
|
|
So, a fabfile to deploy media to a couple of web servers might look something
|
|
like::
|
|
|
|
from fabric.api import *
|
|
|
|
# Hosts to deploy onto
|
|
env.hosts = ['www1.example.com', 'www2.example.com']
|
|
|
|
# Where your project code lives on the server
|
|
env.project_root = '/home/www/myproject'
|
|
|
|
def deploy_static():
|
|
with cd(env.project_root):
|
|
run('./manage.py collectstatic -v0 --noinput')
|
|
|
|
Serving static files from a dedicated media server
|
|
--------------------------------------------------
|
|
|
|
Most larger Django apps use a separate Web server -- i.e., one that's not also
|
|
running Django -- for serving media. This server often runs a different type of
|
|
web server -- faster but less full-featured. Some good choices are:
|
|
|
|
* lighttpd_
|
|
* Nginx_
|
|
* TUX_
|
|
* Cherokee_
|
|
* A stripped-down version of Apache_
|
|
|
|
.. _lighttpd: http://www.lighttpd.net/
|
|
.. _Nginx: http://wiki.nginx.org/Main
|
|
.. _TUX: http://en.wikipedia.org/wiki/TUX_web_server
|
|
.. _Apache: http://httpd.apache.org/
|
|
.. _Cherokee: http://www.cherokee-project.com/
|
|
|
|
Configuring these servers is out of scope of this document; check each server's
|
|
respective documentation for instructions.
|
|
|
|
Since your media server won't be running Django, you'll need to modify the
|
|
deployment strategy to look something like:
|
|
|
|
* When your media changes, run :djadmin:`collectstatic` locally.
|
|
* Push your local :setting:`STATIC_ROOT` up to the media server
|
|
into the directory that's being served. ``rsync`` is a good
|
|
choice for this step since it only needs to transfer the
|
|
bits of static media that have changed.
|
|
|
|
Here's how this might look in a fabfile::
|
|
|
|
from fabric.api import *
|
|
from fabric.contrib import project
|
|
|
|
# Where the static files get collected locally
|
|
env.local_static_root = '/tmp/static'
|
|
|
|
# Where the static files should go remotely
|
|
env.remote_static_root = '/home/www/media.example.com'
|
|
|
|
@roles('media')
|
|
def deploy_static():
|
|
local('./manage.py collectstatic')
|
|
project.rysnc_project(
|
|
remote_dir = env.remote_static_root,
|
|
local_dir = env.local_static_root,
|
|
delete = True
|
|
)
|
|
|
|
.. _staticfiles-from-cdn:
|
|
|
|
Serving static media from a cloud service or CDN
|
|
------------------------------------------------
|
|
|
|
Another common tactic is to serve media from a cloud storage provider like
|
|
Amazon's S3__ and/or a CDN (content delivery network). This lets you ignore the
|
|
problems of serving media, and can often make for faster-loading webpages
|
|
(especially when using a CDN).
|
|
|
|
When using these services, the basic workflow would look a bit like the above,
|
|
except that instead of using ``rsync`` to transfer your media to the server
|
|
you'd need to transfer the media to the storage provider or CDN.
|
|
|
|
There's any number of ways you might do this, but if the provider has an API a
|
|
:doc:`custom file storage backend </howto/custom-file-storage>` will make the
|
|
process incredibly simple. If you've written or are using a 3rd party custom
|
|
storage backend, you can tell :djadmin:`collectstatic` to use it by setting
|
|
:setting:`STATICFILES_STORAGE` to the storage engine.
|
|
|
|
For example, if you've written an S3 storage backend in
|
|
``myproject.storage.S3Storage`` you could use it with::
|
|
|
|
STATICFILES_STORAGE = 'myproject.storage.S3Storage'
|
|
|
|
Once that's done, all you have to do is run :djadmin:`collectstatic` and your
|
|
media would be pushed through your storage package up to S3. If you later needed
|
|
to swich to a different storage provider, it could be as simple as changing your
|
|
:setting:`STATICFILES_STORAGE` setting.
|
|
|
|
For details on how you'd write one of these backends,
|
|
:doc:`/howto/custom-file-storage`.
|
|
|
|
.. seealso::
|
|
|
|
The `django-storages`__ project is a 3rd party app that provides many
|
|
storage backends for many common file storage APIs (including `S3`__).
|
|
|
|
__ http://s3.amazonaws.com/
|
|
__ http://code.welldev.org/django-storages/
|
|
__ http://code.welldev.org/django-storages/wiki/S3Storage
|
|
|
|
Upgrading from ``django-staticfiles``
|
|
=====================================
|
|
|
|
``django.contrib.staticfiles`` began its life as `django-staticfiles`_. If
|
|
you're upgrading from `django-staticfiles`_ to ``django.contrib.staticfiles``,
|
|
you'll need to make a few changes:
|
|
|
|
* Application files should now live in a ``static`` directory in each app
|
|
(`django-staticfiles`_ used the name ``media``, which was slightly
|
|
confusing).
|
|
|
|
* The management commands ``build_static`` and ``resolve_static`` are now
|
|
called :djadmin:`collectstatic` and :djadmin:`findstatic`.
|
|
|
|
* The settings ``STATICFILES_PREPEND_LABEL_APPS``,
|
|
``STATICFILES_MEDIA_DIRNAMES`` and ``STATICFILES_EXCLUDED_APPS`` were
|
|
removed.
|
|
|
|
* The setting ``STATICFILES_RESOLVERS`` was removed, and replaced by the new
|
|
:setting:`STATICFILES_FINDERS`.
|
|
|
|
* The default for :setting:`STATICFILES_STORAGE` was renamed from
|
|
``staticfiles.storage.StaticFileStorage`` to
|
|
``staticfiles.storage.StaticFilesStorage``
|
|
|
|
* If using :djadmin:`runserver` for local development (and the
|
|
:setting:`DEBUG` setting is ``True``), you no longer need to add
|
|
anything to your URLconf for serving static files in development.
|
|
|
|
Learn more
|
|
==========
|
|
|
|
This document has covered the basics and some common usage patterns. For
|
|
complete details on all the settings, commands, template tags, and other pieces
|
|
include in ``django.contrib.staticfiles``, see :doc:`the statcfiles reference
|
|
</ref/contrib/staticfiles>`.
|