Django-addons
=============

Django-addons is a bunch of code that makes writing addon/plugins for your
Django project much easier. Add django-addons to your Django project and 
you can drop all the addons to /MyDjangoProject/addons folder.

Features:
* Addons overview page
* Automatic signal connecting of addons
* Automatic URL discovery of addons
* Template hooking system (inject code from addons to your main project)
* Django-staticfiles to serve site media from each addon
* Django-notifications support (automatic registration of noticetypes)
* Per addon localization
* Per addon settings
* Disabling addons via ./manage.py addons

Addon structure
===============
Addon is basically a Django app living inside /MyDjangoProject/addons/:

    /MyDjangoProject/addons/example/__init__.py
    /MyDjangoProject/addons/example/models.py
    /MyDjangoProject/addons/example/views.py
    /MyDjangoProject/addons/example/handlers.py
    /MyDjangoProject/addons/example/locale/*/*.po
    /MyDjangoProject/addons/example/settings/00-base.conf
    /MyDjangoProject/addons/example/templates/*.html
    /MyDjangoProject/addons/example/templatetags/*.py
    ...

Metainfo
========
The file /MyDjangoProject/addons/example/__init__.py should contain 
metaclass with information about the addon:

    class Meta:
        title = "About page for Project X"
        author = "John Smith"
        description = "Adds about page under /about"
        url = "/about"

Signals
=======

/MyDjangoProject/addons/example/handlers.py:

    from projects.signals import blah
    def my_cool_handler():
        do_blah

    # NB! Django-Addons is looking for this function:
    def connect():
        blah.connect(my_cool_handler)

Django-notifications support
============================
/MyDjangoProject/addons/notifications.py:

    # This is the suggested way of doing thing at the moment
    # We'll probably move to signal based architecture once django-notification
    # guys will add the features what we need to make it happen
    from common.notifications import NOTICE_TYPES
    NOTICE_TYPES += [ blah ]

Templates
=========

/MyDjangoProject/addons/example/templates/*.html:

    Templates that **can** overload your Django project templates

/MyDjangoProject/addons/example/templates/example/additional_buttons.html:

    Addon specific templates that should **not** overload your Django project templates.
    These can be included in your project code by: hook "additional_buttons.html"
    This way every file from each addon named "additional_buttons.html" will be 
    merged together in your project templates

Dependencies
============
We suggest doing dependency checks in models.py:

    try:
	import Blah
    except ImportError
	raise AddonError("You need Blah to use this addon")


Overriding default behaviour in addon
=====================================
We suggest using jQuery to achieve this, this requires that your project
has properly defined 'id' attributes


Site media
==========
We're using django-staticfiles to serve /media folder from each plugin root.

Lets say you have image.png in /MyDjangoProject/addons/MyPlugin/media/image.png.

In the templates you can do something like this (be careful with slashes!):

<img src="{{ STATIC_URL }}myPlugin/image.png"/>

In case you have DEBUG=True, the URLconf does it's magic and everything works without running 
./manage.py build_static. For real-life deployment you should set DEBUG=False and run the command
http://localhost:8000/projects/p/django-registration/c/default/

Internationalization
====================
To internationalize your addon go to /MyDjangoProject/addon/example and run:
  django-admin.py makemessages --all

To generate *.mo files for the whole project in /MyDjangoProject run:
  ./manage.py compilemessages

Issues
======
Signal execution order is not determined. Solution: Addons can emit their own signals and other addons 
can catch them to determine the order of execution. Signal dependencies -> Addon dependencies. 
The solution on the main project side is to provide signals for each small step so the addon would register 
themselves at the most logical point. With step-by-step signals there is no need to trap a part of 
your Django project code in addon to control it's behaviour.

Conclusion: ordering of addons is out of the scope of addon subsystem. If addon1 handler needs addon2 handler 
to run first, then addon1 developer just includes it in their package and django-addons doesn't care about this.


Coding tips
===========
Instead of importing models directly we strongly suggest using get_model function provided by Django.
It also solves many other situations. 

For example if you want to access your addon model from your addon templatetags.
With import statement you would write something like this

  from full.prefix.to.addons.addon_name.models import MyModel

But with get_model it's much nicer:

  MyModel = get_model('addon_name', 'MyModel')


Disabling addons
================
By default all addons dropped in ADDONS_ROOT directory are enabled.
You can optionally disable addons via management command 'addons':
  ./manage.py addons                  - list addons
  ./manage.py addons -e ADDON_NAME    - enable addon
  ./manage.py addons -d ADDON_NAME    - disable addon
Information about disabled addons will be stored in ADDONS_ROOT/disabled.conf

TODO
====
* Addon dependencies
* Better hooking system
* Separate addon developer and addon subsystem user documentation
