mirror of
https://github.com/django/django.git
synced 2024-12-23 17:46:27 +00:00
c4c7fbcc0d
Many thanks to Daniel Greenfeld, James Aylett, Marc Tamlyn, Simon Williams, Danilo Bargen and Luke Plant for their work on this.
511 lines
20 KiB
Plaintext
511 lines
20 KiB
Plaintext
=====================
|
|
Managing static files
|
|
=====================
|
|
|
|
.. 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 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
|
|
static files 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 static files
|
|
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``
|
|
====================================
|
|
|
|
Basic usage
|
|
-----------
|
|
|
|
1. Put your static files somewhere that ``staticfiles`` will find them.
|
|
|
|
By default, this means within ``static/`` subdirectories of apps in your
|
|
:setting:`INSTALLED_APPS`.
|
|
|
|
Your project will probably also have static assets that aren't tied to a
|
|
particular app. The :setting:`STATICFILES_DIRS` setting is a tuple of
|
|
filesystem directories to check when loading static files. It's a search
|
|
path that is by default empty. See the :setting:`STATICFILES_DIRS` docs
|
|
how to extend this list of additional paths.
|
|
|
|
Additionally, see the documentation for the :setting:`STATICFILES_FINDERS`
|
|
setting for details on how ``staticfiles`` finds your files.
|
|
|
|
2. Make sure that ``django.contrib.staticfiles`` is included in your
|
|
:setting:`INSTALLED_APPS`.
|
|
|
|
For :ref:`local development<staticfiles-development>`, if you are using
|
|
:ref:`runserver<staticfiles-runserver>` or adding
|
|
:ref:`staticfiles_urlpatterns<staticfiles-development>` to your
|
|
URLconf, you're done with the setup -- your static files will
|
|
automatically be served at the default (for
|
|
:djadmin:`newly created<startproject>` projects) :setting:`STATIC_URL`
|
|
of ``/static/``.
|
|
|
|
3. You'll probably need to refer to these files in your templates. The
|
|
easiest method is to use the included context processor which allows
|
|
template code like:
|
|
|
|
.. code-block:: html+django
|
|
|
|
<img src="{{ STATIC_URL }}images/hi.jpg" alt="Hi!" />
|
|
|
|
See :ref:`staticfiles-in-templates` for more details, **including** an
|
|
alternate method using a template tag.
|
|
|
|
Deploying static files in a nutshell
|
|
------------------------------------
|
|
|
|
When you're ready to move out of local development and deploy your project:
|
|
|
|
1. Set the :setting:`STATIC_URL` setting to the public URL for your static
|
|
files (in most cases, the default value of ``/static/`` is just fine).
|
|
|
|
2. Set the :setting:`STATIC_ROOT` setting to point to the filesystem path
|
|
you'd like your static files collected to when you use the
|
|
:djadmin:`collectstatic` management command. For example::
|
|
|
|
STATIC_ROOT = "/home/jacob/projects/mysite.com/sitestatic"
|
|
|
|
3. Run the :djadmin:`collectstatic` management command::
|
|
|
|
./manage.py collectstatic
|
|
|
|
This'll churn through your static file storage and copy them into the
|
|
directory given by :setting:`STATIC_ROOT`.
|
|
|
|
4. Deploy those files by configuring your webserver of choice to serve the
|
|
files in :setting:`STATIC_ROOT` at :setting:`STATIC_URL`.
|
|
|
|
:ref:`staticfiles-production` covers some common deployment strategies
|
|
for static files.
|
|
|
|
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 need 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 files at all. You can, however, use
|
|
:func:`django.views.static.serve` view for serving :setting:`MEDIA_ROOT`
|
|
in development; see :ref:`staticfiles-other-directories`.
|
|
|
|
.. _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://static.example.com/static/myimage.jpg" alt="Sample image" />
|
|
|
|
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
|
|
static files. 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 static files servers
|
|
only requires changing that single value. Much better!
|
|
|
|
Django includes multiple built-in ways of using 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" alt="Hi!" />
|
|
|
|
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/index>`,
|
|
but in views written by hand you'll need to explicitly use ``RequestContext``
|
|
To see how that works, and to read more details, check out
|
|
:ref:`subclassing-context-requestcontext`.
|
|
|
|
Another option is the :ttag:`get_static_prefix` template tag that is part of
|
|
Django's core.
|
|
|
|
With a template tag
|
|
-------------------
|
|
|
|
The more powerful tool is the :ttag:`static<staticfiles-static>` template
|
|
tag. It builds the URL for the given relative path by using the configured
|
|
:setting:`STATICFILES_STORAGE` storage.
|
|
|
|
.. code-block:: html+django
|
|
|
|
{% load staticfiles %}
|
|
<img src="{% static "images/hi.jpg" %}" alt="Hi!"/>
|
|
|
|
It is also able to consume standard context variables, e.g. assuming a
|
|
``user_stylesheet`` variable is passed to the template:
|
|
|
|
.. code-block:: html+django
|
|
|
|
{% load staticfiles %}
|
|
<link rel="stylesheet" href="{% static user_stylesheet %}" type="text/css" media="screen" />
|
|
|
|
.. note::
|
|
|
|
There is also a template tag named :ttag:`static` in Django's core set
|
|
of :ref:`built in template tags<ref-templates-builtins-tags>` which has
|
|
the same argument signature but only uses `urlparse.urljoin()`_ with the
|
|
:setting:`STATIC_URL` setting and the given path. This has the
|
|
disadvantage of not being able to easily switch the storage backend
|
|
without changing the templates, so in doubt use the ``staticfiles``
|
|
:ttag:`static<staticfiles-static>`
|
|
template tag.
|
|
|
|
.. _`urlparse.urljoin()`: http://docs.python.org/library/urlparse.html#urlparse.urljoin
|
|
|
|
.. _staticfiles-development:
|
|
|
|
Serving static files in development
|
|
===================================
|
|
|
|
The static files tools are mostly designed to help with getting static files
|
|
successfully deployed into production. This usually means a separate,
|
|
dedicated static file 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
|
|
:ref:`runserver<staticfiles-runserver>` management command.
|
|
|
|
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` setting and wire up the view
|
|
to serve static files accordingly. Don't forget to set the
|
|
:setting:`STATICFILES_DIRS` setting appropriately to let
|
|
``django.contrib.staticfiles`` know where to look for files additionally to
|
|
files in app directories.
|
|
|
|
.. 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, when using ``staticfiles_urlpatterns`` your
|
|
:setting:`STATIC_URL` setting can't be empty or a full URL, such as
|
|
``http://static.example.com/``.
|
|
|
|
For a few more details on how the ``staticfiles`` can be used during
|
|
development, see :ref:`staticfiles-development-view`.
|
|
|
|
.. _staticfiles-other-directories:
|
|
|
|
Serving other directories
|
|
-------------------------
|
|
|
|
.. currentmodule:: django.views.static
|
|
.. function:: serve(request, path, document_root, show_indexes=False)
|
|
|
|
There may be files other than your project's static assets that, for
|
|
convenience, you'd like to have Django serve for you in local development.
|
|
The :func:`~django.views.static.serve` view can be used to serve any directory
|
|
you give it. (Again, this view is **not** hardened for production
|
|
use, and should be used only as a development aid; you should serve these files
|
|
in production using a real front-end webserver).
|
|
|
|
The most likely example is user-uploaded content in :setting:`MEDIA_ROOT`.
|
|
``staticfiles`` is intended for static assets and has no built-in handling
|
|
for user-uploaded files, but you can have Django serve your
|
|
:setting:`MEDIA_ROOT` by appending something like this to your URLconf::
|
|
|
|
from django.conf import settings
|
|
|
|
# ... the rest of your URLconf goes here ...
|
|
|
|
if settings.DEBUG:
|
|
urlpatterns += patterns('',
|
|
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
|
|
'document_root': settings.MEDIA_ROOT,
|
|
}),
|
|
)
|
|
|
|
Note, the snippet assumes your :setting:`MEDIA_URL` has a value of
|
|
``'/media/'``. This will call the :func:`~django.views.static.serve` view,
|
|
passing in the path from the URLconf and the (required) ``document_root``
|
|
parameter.
|
|
|
|
.. currentmodule:: django.conf.urls.static
|
|
.. function:: static(prefix, view='django.views.static.serve', **kwargs)
|
|
|
|
Since it can become a bit cumbersome to define this URL pattern, Django
|
|
ships with a small URL helper function
|
|
:func:`~django.conf.urls.static.static` that takes as parameters the prefix
|
|
such as :setting:`MEDIA_URL` and a dotted path to a view, such as
|
|
``'django.views.static.serve'``. Any other function parameter will be
|
|
transparently passed to the view.
|
|
|
|
An example for serving :setting:`MEDIA_URL` (``'/media/'``) during
|
|
development::
|
|
|
|
from django.conf import settings
|
|
from django.conf.urls.static import static
|
|
|
|
urlpatterns = patterns('',
|
|
# ... the rest of your URLconf goes here ...
|
|
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
|
|
|
.. note::
|
|
|
|
This helper function will only be operational in debug mode and if
|
|
the given prefix is local (e.g. ``/static/``) and not a URL (e.g.
|
|
``http://static.example.com/``).
|
|
|
|
.. _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 files change, then arrange for
|
|
the collected static files directory (:setting:`STATIC_ROOT`) to be moved to
|
|
the static file 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 static files from the same server that's already
|
|
serving your site, the basic outline gets modified to look something like:
|
|
|
|
* Push your code up to the deployment server.
|
|
* On the server, run :djadmin:`collectstatic` to copy all the static files
|
|
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-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 file 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 static files 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 server
|
|
--------------------------------------------
|
|
|
|
Most larger Django apps use a separate Web server -- i.e., one that's not also
|
|
running Django -- for serving static files. 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 static file server won't be running Django, you'll need to modify
|
|
the deployment strategy to look something like:
|
|
|
|
* When your static files change, run :djadmin:`collectstatic` locally.
|
|
* Push your local :setting:`STATIC_ROOT` up to the static file 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 files 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/static.example.com'
|
|
|
|
@roles('static')
|
|
def deploy_static():
|
|
local('./manage.py collectstatic')
|
|
project.rsync_project(
|
|
remote_dir = env.remote_static_root,
|
|
local_dir = env.local_static_root,
|
|
delete = True
|
|
)
|
|
|
|
.. _staticfiles-from-cdn:
|
|
|
|
Serving static files from a cloud service or CDN
|
|
------------------------------------------------
|
|
|
|
Another common tactic is to serve static files from a cloud storage provider
|
|
like Amazon's S3__ and/or a CDN (content delivery network). This lets you
|
|
ignore the problems of serving static files, 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 static files to the
|
|
server you'd need to transfer the static files 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
|
|
static files would be pushed through your storage package up to S3. If you
|
|
later needed to switch 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.larlet.fr/django-storages/
|
|
__ http://django-storages.readthedocs.org/en/latest/backends/amazon-S3.html
|
|
|
|
Upgrading from ``django-staticfiles``
|
|
=====================================
|
|
|
|
``django.contrib.staticfiles`` began its life as `django-staticfiles`_. If
|
|
you're upgrading from `django-staticfiles`_ older than 1.0 (e.g. 0.3.4) 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 :ref:`runserver<staticfiles-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 staticfiles reference
|
|
</ref/contrib/staticfiles>`.
|