Metadata-Version: 1.0
Name: djc.recipe
Version: 0.5
Summary: A Django buildout recipe
Home-page: http://open.abstract.it/it/progetti/rilasci-abstract/djc.recipe/
Author: Simone Deponti
Author-email: simone.deponti@abstract.it
License: BSD
Description: .. contents::
        
        This recipe allows you to setup a Django_ project through `zc.buildout`_.
        
        Usage
        *****
        
        The main scope of the recipe is to abstract out the ``settings.py`` file,
        allowing settings to reside inside the buildout instead of having them reside
        into code (leading to an awkard handling of the same in respect to versioning,
        for example). The ``settings.py`` file is generated by a template, either the
        default one, the default one and a user extension, or a totally new one.
        
        The template uses the Tempita_ templating system.
        
        The most basic usage of this recipe is as follows: ::
        
        [buildout]
        parts = django
        
        [django]
        recipe = djc.recipe
        project = my.project
        
        Where ``my.project`` is an importable package containing a ``urls`` module and
        a ``templates`` directory.
        
        As you see, very few options are specified here: the defaults are used to build
        up the ``settings.py`` file.
        
        Of course, real examples tend to be slightly more complex: for example here is
        a buildout used for Satchmo_: ::
        
        [buildout]
        parts =
        omelette
        
        find-links =
        http://dist.plone.org/thirdparty/
        
        versions = versions
        
        eggs =
        PIL
        pysqlite
        Django
        pycrypto
        PyYAML
        django-registration
        django-livesettings
        django-keyedcache
        django-signals-ahoy
        django-caching-app-plugins
        django-threaded-multihost
        sorl-thumbnail
        trml2pdf
        ReportLab
        Satchmo
        example.site
        
        [django]
        recipe = djc.recipe.django
        project = example.site
        settings-template-extension = templates/settings-extension.py.in
        media-origin = satchmo_store:../static
        media-url = static
        admin-media = media
        template-loaders =
        django.template.loaders.filesystem.load_template_source
        django.template.loaders.app_directories.load_template_source
        middleware =
        django.middleware.common.CommonMiddleware
        django.contrib.sessions.middleware.SessionMiddleware
        django.middleware.locale.LocaleMiddleware
        django.contrib.auth.middleware.AuthenticationMiddleware
        django.middleware.doc.XViewMiddleware
        threaded_multihost.middleware.ThreadLocalMiddleware
        satchmo_store.shop.SSLMiddleware.SSLRedirect
        template-context-processors =
        satchmo_store.shop.context_processors.settings
        django.core.context_processors.auth
        apps=
        django.contrib.sites
        satchmo_store.shop
        django.contrib.admin
        django.contrib.auth
        django.contrib.contenttypes
        django.contrib.comments
        django.contrib.sessions
        django.contrib.sitemaps
        registration
        sorl.thumbnail
        keyedcache
        livesettings
        l10n
        satchmo_utils.thumbnail
        satchmo_store.contact
        tax
        tax.modules.no
        tax.modules.area
        tax.modules.percent
        shipping
        product
        payment
        payment.modules.dummy
        satchmo_ext.satchmo_toolbar
        satchmo_utils
        app_plugins
        product.modules.configurable
        authentication-backends =
        satchmo_store.accounts.email-auth.EmailBackend
        django.contrib.auth.backends.ModelBackend
        languages =
        en English
        it Italiano
        language-code = en-us
        timezone = Europe/Rome
        site-name = Satchmo Sample Site
        site-domain = localhost
        site-id = 1
        debug = true
        
        [versions]
        PIL = 1.1.7
        trml2pdf = 0.1
        Satchmo = 0.9-1
        
        As you can see, a lot more options are used, including an extension template
        (the default template with appended the given template).
        
        See Options_, `Default template options`_ and `Example usage`_ for more
        details.
        
        Links
        *****
        
        - Code repository: http://gitorious.org/djc-recipe/djc-recipe
        - Report bugs at http://open.abstract.it/it/progetti/rilasci-abstract/djc.recipe/issues
        - Comments and questions at info@abstract.it
        
        .. _Django: http://www.djangoproject.com/
        .. _`zc.buildout`: http://www.buildout.org/
        .. _Satchmo: http://www.satchmoproject.com
        
        
        Detailed Documentation
        **********************
        
        Options
        =======
        
        The options of this recipe are not fixed, as many of those are used exclusively
        within the settings template file (see Templating_).
        
        Here we present the options that have an impact on the recipe aswell:
        
        project
        This identifies a python module (in dotted notation) that can serve as
        project package. The bare minimum for a project package is to contain a
        ``urls.py`` file and a ``templates`` directory. It is mandatory unless both
        the ``urlconf`` and ``templates`` option are defined.
        
        urlconf
        Identifies the module that contains the url definition: if omitted the file
        ``urls.py`` inside the module given as ``project`` is used.
        
        templates
        Identifies the templates directory. If omitted, the directory named
        ``templates`` located in the module given as ``project`` is used.
        
        static-directory
        Identifies the folder into which static content (images, CSS and
        Javascripts) will go. Relatives path are considered relative to the
        buildout directory. The directory will be created if not present, and
        nothing will be done if it already exists. If omitted, defaults to
        ``static``.
        
        media-directory
        Identifies the folder into which uploaded files will go. If omitted,
        defaults to ``media``.
        
        settings-template
        If specified, the given template is used to generate the ``settings.py``
        file, if not provided, the default template will be used. See Templating_
        for more details.
        
        settings-template-extension
        If specified, the given template is appended to the template specified by
        ``settings template`` or to the default one.
        
        static-origin
        If specified, defines directories from which to copy the static files that
        have to go in ``static-directory``: see `Static origin`_ for more details.
        
        media-origin
        If specified, defines directories from which to copy the data files that
        have to go in ``media-directory``: see ``static-origin`` option for
        details.
        
        base-settings
        A settings module (only absolute imports) that is extended by the current
        settings.
        If specified, the defaults for ``apps``, ``middleware`` and
        ``template-loaders`` becomes an empty string (resulting into them not being
        written at all).
        
        wsgi
        Defaults to ``false``. If set to ``true`` (or ``on`` or ``1``) creates a
        script in ``parts/$partname`` named ``$partname.wsgi.py`` that can be used
        as WSGI script in Apache or other WSGI enabled webserver.
        
        wsgi-logfile
        If set, the log will be redirected here: defaults to not being set.
        
        
        Advanced options
        ----------------
        
        .. note:: All these options are optional and should not be necessary under
        normal conditions, but might be useful to advanced users.
        
        The following advanced options are supported:
        
        extra-paths
        A number of non-standard paths where additional python modules are located.
        
        pth-files
        A number of pth-files from which to load additional python modulesthat
        should be present in the buildout.
        
        
        Templating
        ==========
        
        The ``settings.py`` file is generated by interpolating the options of the
        buildout section with a template, be it the default one or the one provided by
        the ``settings-template`` option.
        
        The template must be a valid Tempita_ template, to which the whole options of
        the current buildout section is passed as namespace, integrated as follow:
        
        1. In the options name, all minuses (``-``) are converted to underscores
        (``_``)
        
        2. The option ``name`` and ``secret`` are added, respectively mapping to the
        buildout section name and to a randomly-generated secret [#]_.
        
        3. A serie of functions is added to the namespace to simplify the handling of
        some situations, see below for more details.
        
        
        Functions
        ---------
        
        A certain number of functions can be used inside the templates:
        
        absolute_url
        Takes a path and, if it is relative, concatenates it with the buildout
        location to make it absolute.
        
        listify
        Takes a chunk of data, splits it into lines, trims those lines and returns
        the obtained list, from which void strings are purged.
        
        rfc822tuplize
        This function is quite specialized and takes any string in the form
        ``Full Name <email.address@example.com>`` into a tuple composed by the full
        name and the mail address. It will return a tuple with the unchanged data
        if the data fed in does not conform to the specifics.
        
        boolify
        This functions returns ``True`` if the data fed is is any of ``true``,
        ``on``, ``1`` (case- insensitive) and ``False`` otherwise
        
        join
        Equivalent of string's ``join()`` method, with the data to join as first
        parameter, the *infix* as second and two optional parameters *prefix*
        (added just one to the beginning) and *suffix* (added just one to the end)
        
        
        Default template options
        ------------------------
        
        The default template accepts a number of options. They are to be considered all
        optional, as sensible defaults will be provided if omitted.
        
        media-url
        The static content prefix path. Defaults to ``media``
        
        admin-media
        The admin only static content prefix path. Defaults to ``admin_media``
        
        database-engine
        The database engine to use: defaults to ``sqlite``
        
        database-name
        The name of the database to use: defaults to ``storage.db``
        
        database-user
        The username to use when connecting to the database server. Defaults to
        empty string.
        
        database-password
        The password to use when connecting to the database server. Defaults to
        empty string.
        
        database-host
        The host on which the database server resides. Defaults to empty string.
        
        database-port
        The port on which the database server accepts connections. Defaults to
        empty string.
        
        timezone
        The timezone: defaults to ``America/Chicago``
        
        language-code
        The language code: defaults to ``en-us``
        
        admins
        The list of site admins, in *RFC822* form. Defaults to
        ``John Smith <root@localhost>``
        
        managers
        The list of managers: same as for *admins*. Defaults to copy the value of
        *admins*
        
        middleware
        The list of middleware classes to load. If an empty string, the value is
        not written at all.
        
        apps
        The list of apps to load. If empty, the value is not written at all.
        
        template-loaders
        The list of template loaders to use. If empty, the value is not written at
        all.
        
        debug
        If ``true``, activates debug mode. Defaults to ``false``
        
        internal-ips
        The IPs that are allowed to see full stack traces when in debug. Defaults
        to ``127.0.0.1``
        
        site-id
        The Django site id. Defaults to unset.
        
        template-context-processors
        The Django template context processors. Defaults to unset.
        
        authentication-backends
        The Django authentication backends. Defaults to unset
        
        languages
        A list of supported languages in the form ``code Fullname``, for example
        ``en-us English (US)``. Defaults to unset.
        
        smtp-host
        The SMTP host to use when sending mail. Defaults to ``localhost``.
        
        smtp-port
        The SMTP server port. Defaults to 25.
        
        smtp-user
        The username to use to connect to the SMTP server. Defaults to unset.
        
        smtp-password
        The password to use to connect to the SMTP server. This is not valid if
        ``smtp-user`` is not set aswell. Defaults to unset.
        
        smtp-tls
        Whether TLS should be used when connecting to the SMTP server (boolean
        option). Defaults to ``false``.
        
        site-domain
        The site domain. Defaults to unset.
        
        site-name
        The site title. Defaults to unset.
        
        cache-backend
        The cache backend. Defaults to ``locmem:///``.
        
        cache-timeout
        The cache timeout in seconds. Defaults to ``60*5``.
        
        cache-prefix
        The cache prefix (prefixed at all cache IDs). Defaults to ``Z``.
        
        fixture-dirs
        The directories into which search for fixtures. Not set by default.
        
        
        Example usage
        =============
        
        As first thing, we need to have a Django project egg around. We have made a
        very simple one just for testing and we have created a source distribution for
        it located in ``packages``.
        
        This is of course not the only way you can distribute and obtain the project
        egg: for example, during developement, it is recommended to use `mr.developer`_
        for that.
        
        That cleared, we create the most simple buildout conceivable using this recipe ::
        
        >>> write('buildout.cfg',
        ... """
        ... [buildout]
        ... parts = django
        ... offline = false
        ... index = http://pypi.python.org/simple/
        ... find-links = packages
        ...
        ... [django]
        ... recipe = djc.recipe
        ... project = dummydjangoprj
        ... """)
        
        And run it ::
        
        >>> print "start\n", system(buildout)
        start
        ...
        Installing django.
        django: Specified project 'dummydjangoprj' not found, attempting install
        Getting distribution for 'dummydjangoprj'.
        ...
        django: Generating settings in ...
        django: Making empty media directory ...
        django: Creating script at ...
        Generated script ...
        <BLANKLINE>
        
        This generated some files and directories for us:
        
        1. A Django ``manage.py`` wrapper located at ``bin/django``
        
        2. A media directory (empty) at ``static`` (default option)
        
        3. A settings file located in ``parts/django/settings.py``
        
        So, as we can see, we have a ``static`` directory in the root, a ``bin/django``
        script and a ``parts/django`` part ::
        
        >>> ls(sample_buildout)
        -  .installed.cfg
        -  .secret.cfg
        d  bin
        -  buildout.cfg
        d  develop-eggs
        d  eggs
        d  media
        d  packages
        d  parts
        d  src
        d  static
        >>> ls('bin')
        -  buildout
        -  django
        >>> ls('parts')
        d  django
        
        Let's look at this first ::
        
        >>> ls('parts', 'django')
        -  settings.py
        >>> cat('parts', 'django', 'settings.py')
        ADMINS = (
        <BLANKLINE>
        ('John Smith', 'root@localhost'),
        )
        MANAGERS = ADMINS
        <BLANKLINE>
        <BLANKLINE>
        DATABASE_ENGINE = 'sqlite3'
        DATABASE_NAME = 'storage.db'
        DATABASE_USER = ''
        DATABASE_PASSWORD = ''
        DATABASE_HOST = ''
        DATABASE_PORT = ''
        <BLANKLINE>
        TIME_ZONE = 'America/Chicago'
        <BLANKLINE>
        LANGUAGE_CODE = 'en-us'
        <BLANKLINE>
        STATIC_ROOT = '.../static'
        <BLANKLINE>
        STATIC_URL = '/static/'
        <BLANKLINE>
        MEDIA_ROOT = '.../media'
        <BLANKLINE>
        MEDIA_URL = '/media/'
        <BLANKLINE>
        ADMIN_MEDIA_PREFIX = '/admin_media/'
        <BLANKLINE>
        SECRET_KEY = '...'
        <BLANKLINE>
        ROOT_URLCONF = 'dummydjangoprj.urls'
        <BLANKLINE>
        <BLANKLINE>
        TEMPLATE_DIRS = (
        '.../dummydjangoprj/templates',
        )
        <BLANKLINE>
        EMAIL_HOST = 'localhost'
        EMAIL_PORT = 25
        EMAIL_USE_TLS = False
        <BLANKLINE>
        CACHE_BACKEND = 'locmem:///'
        CACHE_TIMEOUT = 60*5
        CACHE_PREFIX = 'Z'
        
        As you can see, this is pretty much the standard Django ``settings.py`` as
        created by Django's ``django-admin``. It has the peculiarity of not residing in
        a module, however, but is loaded at run time into the appropriate manage script
        as a *ghost* module named ``_django_settings``.
        
        Let's have a look at the manage script ::
        
        >>> cat('bin', 'django')
        #!...
        <BLANKLINE>
        import sys
        sys.path[0:0] = [
        ...
        ]
        <BLANKLINE>
        import djc.recipe.manage
        <BLANKLINE>
        if __name__ == '__main__':
        djc.recipe.manage.main('.../parts/django/settings.py')
        
        As we can see, the ``main()`` function of the ``manage`` module is called,
        passing in the file with the settings as only argument.
        
        Template overriding
        -------------------
        
        As it was said in Templating_, the default template can be overridden or
        extended.
        
        Let's start by extending it: ::
        
        >>> write('template-extension.py.in',
        ... """
        ... # Here we can extend the template, using variables pulled in from the
        ... # buildout section, with the dashes converted to underscores
        ... MY_CONFIG_VARIABLE = '{{config_variable_one}}'
        ... """)
        >>> write('buildout.cfg',
        ... """
        ... [buildout]
        ... parts = django
        ... offline = false
        ... index = http://pypi.python.org/simple/
        ... find-links = packages
        ...
        ... [django]
        ... recipe = djc.recipe
        ... project = dummydjangoprj
        ... settings-template-extension = template-extension.py.in
        ... config-variable-one = test
        ... """)
        
        Launch the buildout and then take a look at the generated ``settings.py``
        file ::
        
        >>> print system(buildout)
        Uninstalling django.
        Installing django.
        ...
        Generated script ...
        <BLANKLINE>
        >>> cat('parts', 'django', 'settings.py')
        ADMINS = (
        <BLANKLINE>
        ('John Smith', 'root@localhost'),
        )
        MANAGERS = ADMINS
        <BLANKLINE>
        <BLANKLINE>
        DATABASE_ENGINE = 'sqlite3'
        DATABASE_NAME = 'storage.db'
        DATABASE_USER = ''
        DATABASE_PASSWORD = ''
        DATABASE_HOST = ''
        DATABASE_PORT = ''
        <BLANKLINE>
        TIME_ZONE = 'America/Chicago'
        <BLANKLINE>
        LANGUAGE_CODE = 'en-us'
        <BLANKLINE>
        STATIC_ROOT = '.../static'
        <BLANKLINE>
        STATIC_URL = '/static/'
        <BLANKLINE>
        MEDIA_ROOT = '.../media'
        <BLANKLINE>
        MEDIA_URL = '/media/'
        <BLANKLINE>
        ADMIN_MEDIA_PREFIX = '/admin_media/'
        <BLANKLINE>
        SECRET_KEY = '...'
        <BLANKLINE>
        ROOT_URLCONF = 'dummydjangoprj.urls'
        <BLANKLINE>
        <BLANKLINE>
        TEMPLATE_DIRS = (
        '.../dummydjangoprj/templates',
        )
        <BLANKLINE>
        EMAIL_HOST = 'localhost'
        EMAIL_PORT = 25
        EMAIL_USE_TLS = False
        <BLANKLINE>
        CACHE_BACKEND = 'locmem:///'
        CACHE_TIMEOUT = 60*5
        CACHE_PREFIX = 'Z'
        <BLANKLINE>
        <BLANKLINE>
        # Extension template template-extension.py.in
        <BLANKLINE>
        <BLANKLINE>
        # Here we can extend the template, using variables pulled in from the
        # buildout section, with the dashes converted to underscores
        MY_CONFIG_VARIABLE = 'test'
        
        As you can see, the aditional template has been simply appended to the default,
        and the variable ``config-variable-one`` has been substituted.
        
        If, instead, we totally override the template: ::
        
        >>> write('template.py.in',
        ... """
        ... # Total override
        ... FOODS = (
        ...     {{join(listify(foods), "',\\n    '", "'", "',")}}
        ... )
        ... """)
        >>> write('buildout.cfg',
        ... """
        ... [buildout]
        ... parts = django
        ... offline = false
        ... index = http://pypi.python.org/simple/
        ... find-links = packages
        ...
        ... [django]
        ... recipe = djc.recipe
        ... project = dummydjangoprj
        ... settings-template = template.py.in
        ... foods =
        ...     spam
        ...     spam
        ...     eggs
        ...     spam
        ... """)
        
        
        Launch the buildout and then take a look at the generated ``settings.py``
        file ::
        
        >>> print system(buildout)
        Uninstalling django.
        Installing django.
        ...
        Generated script ...
        <BLANKLINE>
        >>> cat('parts', 'django', 'settings.py')
        # Total override
        FOODS = (
        'spam',
        'spam',
        'eggs',
        'spam',
        )
        
        As you can see, the builtin template has been totally discarded.
        
        Static origin
        =============
        
        Static files are generally not served through Django_, but instead the
        front-end web server takes care to serve them by exposing a directory on the
        filesystem to the web.
        
        However, many static files (think ``.js`` or ``.css``) are part of the
        functionality of a project or application, and would be interesting to be able
        to distribute them alongside the code.
        
        .. note:: The method here described works only for applications and packages
        that are not installed as zipped modules: for example the egg default format
        is a zipped file that does not get extracted after installation unless a
        proper option is passed to ``easy_install``
        
        The relevant resources can be included in the distributed package and use of
        the ``static-origin`` option will allow them to be copied into the
        ``static-directory`` folder (see Options_).
        
        A similar feature is present for media files (e.g. image uploads) as well
        (option ``media-origin``, which ends up into ``media-directory``).
        
        ``static-origin`` can contain a list of static file sources, and each item of
        the list can be either in the form ``package:directory`` or
        ``package:directory:destination``; ``package`` being the full dotted name of
        the importable module, ``directory`` the path to the directory inside the
        module containing static data, and ``destination`` an optional subdirectory
        inside ``static-directory`` where to copy the files.
        
        Let's then begin from the first, simple case, with a single source of static
        data.
        
        The source of static data is the package ``dummydjangoapp1``, residing as a
        developement package inside ``src``. ::
        
        >>> ls('src', 'dummydjangoapp1', 'dummydjangoapp1', 'static')
        -  lib1.js
        -  main.css
        >>> cat('src', 'dummydjangoapp1', 'dummydjangoapp1', 'static', 'main.css')
        body { font-family: "Helvetica" "Arial" sans-serif; }
        
        Let's create a buildout config and run it ::
        
        >>> write('buildout.cfg',
        ... """
        ... [buildout]
        ... parts = django
        ... offline = false
        ... index = http://pypi.python.org/simple/
        ... find-links = packages
        ... develop = src/dummydjangoapp1
        ... eggs = dummydjangoapp1
        ...
        ... [django]
        ... recipe = djc.recipe
        ... project = dummydjangoprj
        ... static-directory = static
        ... static-origin = dummydjangoapp1:static
        ... """)
        >>> rmdir('static')
        >>> print system(buildout)
        Develop: '.../dummydjangoapp1'
        ...
        Uninstalling django.
        Installing django.
        ...
        django: Making media directory '.../static'
        ...
        Generated script ...
        <BLANKLINE>
        
        And now let's see what's in ``static`` ::
        
        >>> ls('static')
        -  lib1.js
        -  main.css
        >>> cat('static', 'main.css')
        body { font-family: "Helvetica" "Arial" sans-serif; }
        
        Let's now try using *two* sources: the second is another dummy app, named
        ``dummydjangoapp2``, that like the first one resides in ``src``.
        
        Let's see what's in its ``static`` for us: ::
        
        >>> ls('src', 'dummydjangoapp2', 'dummydjangoapp2', 'static')
        -  lib2.js
        -  main.css
        
        It seems this app too defines a ``main.css``, so let's look at the content: ::
        
        >>> cat('src', 'dummydjangoapp2', 'dummydjangoapp2', 'static', 'main.css')
        h1 { color: #92B8D8; }
        
        But this poses a problem! What happens when I put this as second source, and
        both define ``main.css``? Well, the intuitive thing to do here is probably to
        override the file, so that the source at the bottom is the top *skin layer*.
        
        So if we have this buildout ::
        
        >>> write('buildout.cfg',
        ... """
        ... [buildout]
        ... parts = django
        ... offline = false
        ... index = http://pypi.python.org/simple/
        ... find-links = packages
        ... develop =
        ...     src/dummydjangoapp1
        ...     src/dummydjangoapp2
        ... eggs =
        ...     dummydjangoapp1
        ...     dummydjangoapp2
        ...
        ... [django]
        ... recipe = djc.recipe
        ... project = dummydjangoprj
        ... static-directory = static
        ... static-origin =
        ...     dummydjangoapp1:static
        ...     dummydjangoapp2:static
        ... """)
        
        It is reasonable to expect that, after running it, the content of the
        ``main.css`` file is the one provided by the version held by
        ``dummydjangoapp2`` rather than the one held by ``dummydjangoapp2``.
        
        A quick run and inspect confirms this: ::
        
        >>> rmdir('static')
        >>> print system(buildout)
        Develop: '.../dummydjangoapp1'
        ...
        Uninstalling django.
        Installing django.
        ...
        django: Making media directory '.../static'
        ...
        Generated script ...
        <BLANKLINE>
        >>> ls('static')
        -  lib1.js
        -  lib2.js
        -  main.css
        >>> cat('static', 'main.css')
        h1 { color: #92B8D8; }
        
        However, I might not want the ``main.css`` override to happen, or any other
        clash between applications, for that matter. That is easily solved by a
        buildout written like this ::
        
        >>> write('buildout.cfg',
        ... """
        ... [buildout]
        ... parts = django
        ... offline = false
        ... index = http://pypi.python.org/simple/
        ... find-links = packages
        ... develop =
        ...     src/dummydjangoapp1
        ...     src/dummydjangoapp2
        ... eggs =
        ...     dummydjangoapp1
        ...     dummydjangoapp2
        ...
        ... [django]
        ... recipe = djc.recipe
        ... project = dummydjangoprj
        ... static-directory = static
        ... static-origin =
        ...     dummydjangoapp1:static:app1
        ...     dummydjangoapp2:static:app2
        ... """)
        
        It is to be noticed that the ``static-origin`` values have now three elements,
        the latter being the destination directory, which is defined as a subdirectory
        of ``static``: in this case, both apps live in their subdirectory and no clash
        happens ::
        
        >>> rmdir('static')
        >>> print system(buildout)
        Develop: '.../dummydjangoapp1'
        ...
        Uninstalling django.
        Installing django.
        ...
        django: Making media directory '.../static'
        ...
        Generated script ...
        <BLANKLINE>
        >>> ls('static')
        d  app1
        d  app2
        >>> ls('static', 'app1')
        -  lib1.js
        -  main.css
        >>> cat('static', 'app1', 'main.css')
        body { font-family: "Helvetica" "Arial" sans-serif; }
        >>> ls('static', 'app2')
        -  lib2.js
        -  main.css
        >>> cat('static', 'app2', 'main.css')
        h1 { color: #92B8D8; }
        
        Of course, this behaviour is not usefol only in this case: an application might
        actually require you to put the static files in a precise subdirectory
        irrespective of the fact that other apps might be present or a clash occur.
        
        WSGI
        ====
        
        The ``wsgi`` option will create a small module [#]_ inside ``parts``, that will
        allow you to hook your application to an upstream ``wsgi`` server.
        
        In order to have the ``buildout``, we must set the ``wsgi`` option of the
        recipe to ``true``: ::
        
        >>> write('buildout.cfg',
        ... """
        ... [buildout]
        ... parts = django
        ... offline = false
        ... index = http://pypi.python.org/simple/
        ... find-links = packages
        ...
        ... [django]
        ... recipe = djc.recipe
        ... project = dummydjangoprj
        ... wsgi = true
        ... """)
        
        And launch the buildout: ::
        
        >>> print "start\n", system(buildout)
        start
        ...
        Installing django.
        django: Specified project 'dummydjangoprj' not found, attempting install
        django: Generating settings in ...
        ...
        django: Creating script at .../bin/django
        Generated script '.../bin/django'.
        django: Creating script at .../parts/django/djc_recipe_django/app.py
        Generated script '.../parts/django/djc_recipe_django/app.py'.
        <BLANKLINE>
        
        The script will then create inside ``parts/<part_name>/djc_recipe_<part_name>``
        a python module containing an ``app.py`` file, which can be loaded by
        ``Apache`` or ``uwsgi``: ::
        
        >>> ls('parts', 'django', 'djc_recipe_django')
        -  __init__.py
        -  app.py
        >>> cat('parts', 'django', 'djc_recipe_django', 'app.py')
        #!...
        <BLANKLINE>
        <BLANKLINE>
        import sys
        sys.path[0:0] = [
        ...
        ]
        <BLANKLINE>
        import djc.recipe.wsgi
        <BLANKLINE>
        application = djc.recipe.wsgi.main('.../parts/django/settings.py')
        
        
        This will take care to inject all the needed paths into ``sys.path``, so no
        further meddling should be needed.
        
        Most *WSGI* servers do handle logging effectively by themselves, however if
        this was not the case, an option to have a separate log output can be used:
        ``wsgi-logfile``, if set, will cause all the applicative log output to be
        written to the specified file.
        
        Let's write the buildout ::
        
        >>> write('buildout.cfg',
        ... """
        ... [buildout]
        ... parts = django
        ... offline = false
        ... index = http://pypi.python.org/simple/
        ... find-links = packages
        ...
        ... [django]
        ... recipe = djc.recipe
        ... project = dummydjangoprj
        ... wsgi = true
        ... wsgi-logfile = wsgi.log
        ... """)
        
        Launch it ::
        
        >>> print "start\n", system(buildout)
        start
        ...
        Installing django.
        django: Specified project 'dummydjangoprj' not found, attempting install
        django: Generating settings in ...
        ...
        django: Creating script at .../bin/django
        Generated script '.../bin/django'.
        django: Creating script at .../parts/django/djc_recipe_django/app.py
        Generated script '.../parts/django/djc_recipe_django/app.py'.
        <BLANKLINE>
        
        And check what changes ::
        
        >>> cat('parts', 'django', 'djc_recipe_django', 'app.py')
        #!...
        <BLANKLINE>
        <BLANKLINE>
        import sys
        sys.path[0:0] = [
        ...
        ]
        <BLANKLINE>
        import djc.recipe.wsgi
        <BLANKLINE>
        application = djc.recipe.wsgi.main(..., logfile = '.../wsgi.log')
        
        As you can see, the log file parameter is passed to the application: it is to
        be noted that all relative paths are intended as relative to the buildout root.
        
        .. _Tempita: http://pypi.python.org/pypi/Tempita/
        
        .. _`mr.developer`: http://pypi.python.org/pypi/mr.developer
        
        .. [#] In all truth, it tries to read it from ``.secret.txt``: that failing the
        secret code is generated and written to said file to be used
        subsequently.
        
        .. [#] The small module is needed because ``uwsgi`` will refuse to load a rogue
        script, but will load a module (hence, with some ``PYTHONPATH`` magic,
        all comes along)
        
        
        
        Contributors
        ************
        
        * Simone Deponti <simone.deponti@abstract.it>, Initial Author
        * Bruno Ripa <bruno.ripa@abstract.it>
        
        Inital developement sponsored by `Abstract Open Solutions`_
        
        .. _`Abstract Open Solutions`: http://www.abstract.it
        
        Change history
        **************
        
        0.5 (2010-06-03)
        ================
        
        .. note:: This release is potentially backwards-incompatible: ``media-url`` and
        ``media-directory`` are now named ``static-url`` and
        ``static-directory`` respectively.
        
        - Fixed MEDIA_URL mess [Simone Deponti]
        
        - Added INTERNAL_IPS support [Simone Deponti]
        
        - No defaults for middleware, template loaders and apps [Simone Deponti]
        
        
        0.3.2 (2010-06-01)
        ==================
        
        - Fixed WSGI support (uwsgi, custom loggers) [Simone Deponti]
        
        - Fixed import bugs [Simone Deponti]
        
        0.3.1 (2010-05-19)
        ==================
        
        aka "Never release between midnight and 6am":
        
        - Fixed absolute path bug for fixture dirs in default template [Simone Deponti]
        
        - Fixed small template extension bug [Simone Deponti]
        
        0.3 (2010-05-19)
        ================
        
        - Added multiple media-origin support [Simone Deponti]
        
        - Added fixture-dirs support [Simone Deponti]
        
        
        0.2 (2010-05-17)
        ================
        
        - First public release [Simone Deponti]
        
        0.1 (2010-04-22)
        ================
        
        - Created package [Simone Deponti]
        
Platform: UNKNOWN
Classifier: Framework :: Buildout
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Build Tools
Classifier: License :: OSI Approved :: BSD License
