==================================================
Dynamically obtain URLs for static media in Django
==================================================


Overview
========

``staticmedia`` provides a lightweight framework for dynamically
obtaining the URLs of your site-level and app-level static media, such
as images and css stylesheets. It lets you avoid hardcoding absolute,
site-specific paths to your static media files in site-level and/or
app-level templates, or in your Python code (declaring widget
assets). It can also be used as an alternative to using a settings
directive, much like 'ADMIN_MEDIA_PREFIX'.

Features
--------

  - A ``{% media %}`` template tag.

  - ``staticmedia.resolve``, a function that you can use to dynamically
    obtain the URL of your static media in your Python code.

  - A submodule and management commands for generating configuraton
    directives for various common web servers.

  - A convenience function for generating urlpatterns that statically
    serve your static media from Django (although this is slow and
    insecure).


Settings
========

``STATICMEDIA_MOUNTS``

Default: ``[]``

A sequence of ``(mount_url, mount_path)`` tuples. The term 'mount' in
this case just means directories on the filesystem, ``mount_path``,
that are expected to be available at a given url on the site,
``mount_url``. Usually these are served by a webserver, but can be
served by Django for testing purposes.


``STATICMEDIA_URL``

Default: ``/appmedia``

The URL prefix to use for each application media mount.


Using static media through ``staticmedia``
==========================================

Bundling media with your application
------------------------------------

To bundle static media with your application, create a ``media``
directory in the root directory of you Django application::

    myapp/
    |---media/
    \---models.py
    \---urls.py

This ``media`` directory will then be picked up by ``staticmedia`` as
a mount point. 

Getting the absolute URL for static media
-----------------------------------------

Static media should be specified relative to mount points Extending
the above application structure::

    myapp/
    |---media/
    |   \---button.png
    \---models.py
    \---urls.py

From Python code::

    >>> import staticmedia
    >>> staticmedia.resolve('button.png')
    '/appmedia/myapp/button.png'

Or from a template::

    {% load media %}
    {% media "button.png" %}


``staticmedia`` first goes through your mounts specified with the
``STATICMEDIA_MOUNTS`` setting, and then through each application
mount (installed applications with a ``media`` directory in the
package). The URL the first mount point in which a 'button.png' file
exists is used.

In the above case, 'button.png' was found in the application media
directory, and since the default value of the ``STATICMEDIA_URL`` is
``'/appmedia'``, the expected URL of the static media file is
'/appmedia/myapp/button.png'.

Suppose you wanted to have a custom 'button.png' for a particular site
to use instead of the one bundled with the application media. You
could add a mount to ``STATICMEDIA_MOUNTS``::

    STATICMEDIA_MOUNTS = (
        ('/sitemedia', '/sites/mysite/sitemedia')
    )

Provided that a '/sites/mysite/sitemedia/button.png' file exists, a
call to ``staticmedia.resolve`` would now return
``'/sitemedia/button.png'``.


Avoiding media filename conflicts
---------------------------------

A good convention to use is to 'namespace' application media, much
like application templates::

    myapp/
    |---media/
    |   \---myapp
    |       \---button.png
    \---models.py
    \---urls.py

Requesting media would look like::

    >>> staticmedia.resolve('myapp/button.png')
    '/appmedia/myapp/myapp/button.png'

    # if we have a 'myapp/button.png' file in the '/sitemedia'
    # mount in the example above, then:

    >>> staticmedia.resolve('myapp/button.png')
    '/sitemedia/myapp/button.png'


``staticmedia`` and web servers
===============================

Normally you want to delegate the serving of your static media to web
servers. ``staticmedia`` comes with a submodule to dynamically
generate configuration directives for some common web servers::

    >>> from staticmedia import conf
    >>> conf.nginx()
    'location /appmedia/myapp { alias /path/to/myapp/media; }'
    >>> conf.apache()
    'Alias "/appmedia/myapp" "/path/to/myapp/media"'

You can also use a management command to print out the configuration
directives::

    $ ./manage.py staticmedia nginx-conf
    location /appmedia/myapp { alias /path/to/myapp/media; }

    $ ./manage.py staticmedia apache-conf
    Alias "/appmedia/myapp" "/path/to/myapp/media"
    
You can also get a generic tab-delineated output::

    $ ./manage.py staticmedia list-mounts
    /appmedia/myapp    /path/to/myapp/media

Or from Python::

    >>> import staticmedia
    >>> staticmedia.get_mount_points()
    (('/appmedia/myapp', '/path/to/myapp/media'),)


Serving static media with Django
================================

A convenience function is provided for automatically generating
urlpatterns that serve your mount points with the
``django.views.static.serve`` method. This isn't recommended outside
of a development environment as its slow and insecure. 

In your urlconf::

    from django.conf.urls.defaults import *
    import staticmedia

    urlpatterns = patterns(
        '',
        # your urls here
    ) + staticmedia.serve()

``staticmedia.serve`` optionally takes one argument, ``debug``, which
controls whether the urlpatterns are generated only if ``DEBUG`` is
``True`` in your settings.
