Overview

#####################
Django-TemplateBlocks
#####################

*******
Summary
*******

Django Templateblocks provides a plugin system and templatetags to manage block
content in your templates.

For the template designer: insert 'block' slots in templates. This gives a list 
of available areas in templates (and consequently in web pages) where blocks 
can be used.

For the developer: create 'plugins' that can render some piece of information. 
This gives a list of available plugins that can be used in the website. Reuse
generic plugins or create specific ones.

For the site administrator: assign plugins to block areas in backend, and 
optionally configure plugins.

This application focuses on layout. It means that its main goal is to help 
rendering content so that it can be displayed in web pages. No more. The 
edition of content and the application of styles onto the layout are less 
important here.

************
Requirements
************

    * `Python`_ >= 2.4 (except Python 3000)
    * `Django`_ >= 1.0
    * `Django-TemplateAddOns`_

.. _`Python`: http://www.python.org
.. _`Django`: http://www.djangoproject.com
.. _`Django-TemplateAddOns`: http://bitbucket.org/benoitbryon/django-templateaddons/

************
Installation
************

Install and configure dependencies. See Requirements.

Get the code. The application resides in the "templateblocks" directory.
The code is available under the BSD license (read LICENSE for details) at
http://bitbucket.org/benoitbryon/django-templateblocks/

Make the ``templateblocks`` directory available in your PYTHONPATH.

Add ``templateblocks`` to your project ``settings.INSTALLED_APPS``::

    INSTALLED_APPS = (
        # ...
        'templateblocks',
        # ...
    )

It you want to let the site administrator interact with templateblocks, you 
should consider enabling the Django's admin.

Synchronise the database::

    $ python manage.py syncdb

That's all.

******************
Template designers
******************

Rendering blocks in templates
=============================

To render blocks into your templates, you have to load the templatetag 
``templateblocks_extras`` and define a block rendering 'area' (or 'slot') with 
the ``render_templateblock`` tag. As an example, to create a block area called
"footer"::

    {% load templateblock %}
    {% templateblock_render 'footer' %}

In the above example, the value 'footer' is considered as the area 'identifier'
or 'code'.

CAUTION: one and only one plugin can be assigned to a given identifier
         ('footer' in the above example). This means that reusing an identifier
         several times (even in different templates) will always use the same 
         plugin, and usually produce the same output. So identify your block
         areas carefully.

Notes:
* {% load templateblock %} simply lets you use the templateblock_render tag.
* this defines a block area (or slot) called "footer". This will be used as an
  identifier in the Django's administration backend, so that the site 
  administrator can assign a plugin to this code. Because the identifier is the
  only link between blocks in template code and plugin instances in database,
  the identifier is considered unique and only one plugin can be assigned to it.
* the output provided by the plugin will be displayed in place.
* sometimes, no plugin will be assigned to the slot. In such a case, nothing is
  displayed (empty slot).
* sometimes, the plugin assigned to the area does not produce output (empty
  plugin).
  
Declaring available slots/areas/locations
=========================================

This action makes it possible for the administration backend to know which
block areas are currently available in templates.

In your settings, add TEMPLATEBLOCKS_SLOTS, which is a list of pairs 
(code, name), where name should be a human-readable version of code::

    gettext = lambda s: s

    TEMPLATEBLOCKS_SLOTS = (
        ('home_welcome', gettext('home / welcome')),
        # ...
    )

**********
Developers
**********

Models: Block and Plugin
========================

The templateblocks application uses two main models: Block and Plugin.

The Block model is the link between templates and plugins. The main role of this
model is to map a template block slot to a plugin. The site administrators will
use Block instances to organize layout.

The Plugin model is an abstract one. It is designed to be the base class of all
plugins that can be assigned to template slots through Block instances. A Plugin
instance is an object that can produce output, usually HTML code.

Some plugins will generate automated output, without having to be configured.
Some plugins will need additional configuration. For such cases, some additional
work is also required to create the corresponding form in admin.

Implementing plugin classes
===========================

Into your application or your project, add a module that will contain the 
Templateblocks plugin classes. You can name it whatever you want. 
For example: ``blocks.py``.

First, import ``Plugin`` base class from templateblocks.models::

    from templateblocks.models import Plugin 

All your Templateblocks plugins must inherit from this class. The Plugin class
is an abstract model.
The most important thing is that your plugin class override the following:
* the "plugin_name" property, which is a human-readable title of the plugin, for
  use in the admin.
* the "plugin_description" property, which is not used at this time, but will
  be displayed as help text in the admin.
* the "render()" method, which signature is: render(self, request, 
  template_context=None).

The most simple plugin looks like this::

    class HelloWorldPlugin(Plugin):
        """
        A minimalist plugin that says "Hello world !". This is a "proof of concept"
        plugin.
        """
        plugin_name = _('hello world')
        plugin_description = _('Displays "Hello world !"')
        
        class Meta:
            """
            Model metadata.
            """
            verbose_name = _('Hello world plugin')
            verbose_name_plural = _('Hello world  plugins')
        
        def render(self, request, template_context=None):
            """
            Returns "Hello world !".
            """
            return u'Hello world !'

You can add model fields to your plugin model. The admin will automatically
display a form to edit these parameters. As an example, here is a another 
simple plugin definition::

    class SimpleContentPlugin(Plugin):
        """
        A plugin that stores a customizable text value and returns it as rendering.
        """
        plugin_name = _('simple content')
        plugin_description = _('Displays the content you set up.')
        
        content = models.TextField(
            _('content'),
        )
        
        class Meta:
            """
            Model metadata.
            """
            verbose_name = _('Simple content plugin')
            verbose_name_plural = _('Simple content plugins')
        
        def render(self, request, template_context=None):
            """
            Renders a template.
            """
            return self.content

Installing plugins classes
==========================

This action makes it possible for the administration backend to know which
block plugins are currently available.

In your settings, add TEMPLATEBLOCKS_PLUGINS, which is a list of pathes to
plugin models::

    TEMPLATEBLOCKS_PLUGINS = (
        'templateblocks.models.HelloWorldPlugin',
        # ...
    )

If some of your plugins have fields, a ModelAdmin subclass will be automatically
used in admin views. If you want to customize the admin change view:
* make sure you have your own ModelAdmin subclass for the plugin
* declare the ModelAdmin subclass to use by replacing
  'path.to.your.Plugin',
  by
  ('path.to.your.Plugin', 'path.to.your.admin.PluginAdmin'),
  in TEMPLATEBLOCKS_PLUGINS setting.
As an example, given PollPlugin and PollPluginAdmin classes::

    TEMPLATEBLOCKS_PLUGINS = (
        'templateblocks.models.HelloWorldPlugin',
        ('yourapp.models.PollPlugin', 'yourapp.admin.PollPluginAdmin'),
    )

Synchronising database with real-life template slots and content plugins
========================================================================

Depending on the way block areas and plugins are registered, some utilities
may be useful to synchronize the work of developers, template designers and
site administrators.

As an example, when a template designer removes a block slot, some actions must
be performed on the corresponding Block instance in database.

*******************
Site administrators
*******************

In site administration backend, the site administrators can manage blocks.
A global list view gives an overview on blocks, focusing on mapping between
template areas and content plugins.
Some of the template slots may be unassigned. For these entries, the site
administrator can choose a plugin in the list of available ones.

*****
Plans
*****

This application has been developed to fit a particular need in website
development process: the edition of template "blocks" by site administrators.

It already has been refactored several times to:
* stay as simple as possible
* do what is expected, no more
* make it possible (and easy) to develop extensions.

That means that this application is designed to be a base for further 
developments. A good example is the plugin concept. But we could imagine other
tools to improve blocks administration, such as nested blocks, publication
options (ordering, publication start date, permissions, ...) or design related 
options (styles). These functionalities may not be added to the templateblocks 
application itself, unless their flexibility and relevance were proven.