diff options
| author | Tim Graham <timograham@gmail.com> | 2013-03-04 06:05:11 -0500 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2013-03-29 19:03:53 -0400 |
| commit | c32fc79aa120a0a129680805aef6731c1c2c7aef (patch) | |
| tree | 708d4431e57676da7181aa514efe6ac33fefafba /docs/howto/static-files | |
| parent | 9916e69bf10ce80645c362edefa150ab70b532b4 (diff) | |
Fixed #19582 - Added a static files tutorial.
Thanks James Pic.
Diffstat (limited to 'docs/howto/static-files')
| -rw-r--r-- | docs/howto/static-files/index.txt | 508 |
1 files changed, 508 insertions, 0 deletions
diff --git a/docs/howto/static-files/index.txt b/docs/howto/static-files/index.txt new file mode 100644 index 0000000000..964b5fab61 --- /dev/null +++ b/docs/howto/static-files/index.txt @@ -0,0 +1,508 @@ +===================== +Managing static files +===================== + +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>`. |
