diff --git a/INSTALL b/INSTALL
index c0733d7a8..29bff06b3 100644
--- a/INSTALL
+++ b/INSTALL
@@ -6,7 +6,7 @@ Requirements
============
- `Python version 2.6+ `_
-- `Django version 1.2+ `_
+- `Django version 1.3+ `_
- `south version 0.7+ `_
- `ldap python module `_
@@ -56,6 +56,10 @@ available:
You may change its password the first time you log into Modoboa.
+Finally, create the directory that will contain static content::
+
+ $ python manage.py collectstatic
+
Time zone and language
----------------------
@@ -249,6 +253,10 @@ requires a migration.
0.9: global UI refactoring, new *limits* extension and more
-----------------------------------------------------------
+.. note::
+ This version requires at least django 1.3. Make sure to update your
+ version before starting to migrate.
+
.. note::
Many files have been renamed/removed for this version. I recommend
that you backup important files (*settings.py*, etc.) elsewhere
@@ -280,6 +288,18 @@ requires a migration.
'django.contrib.auth.backends.ModelBackend',
)
+#. Add ``django.contrib.staticfiles`` to ``INSTALLED_APPS``
+
+#. Add the following new variables::
+
+ STATIC_ROOT = os.path.join(MODOBOA_DIR, 'sitestatic')
+ STATIC_URL = '/static/'
+
+#. Update the following variables (just copy/paste their new values)::
+
+ MEDIA_ROOT = os.path.join(MODOBOA_DIR, 'media')
+ MEDIA_URL = '/media/'
+
#. **For MySQL users only**, add the following option to your database
configuration::
@@ -300,7 +320,12 @@ requires a migration.
$ ./manage.py syncdb --migrate
-#. If you are4 using the *stats* extension, please rename the
+#. Run the following command to initialize the directory that contains
+ static files::
+
+ $ ./manage.py collectstatic
+
+#. If you are using the *stats* extension, please rename the
*/static/stats* directory to */static/graphs*
#. Restart the python instance(s) that serve *Modoboa*
diff --git a/doc/plugin_api.rst b/doc/plugin_api.rst
index 711c77613..93ee3b4ff 100644
--- a/doc/plugin_api.rst
+++ b/doc/plugin_api.rst
@@ -11,9 +11,9 @@ implementation provides the following possibilities:
* Access and modify administrative objects (domains, mailboxes, etc.)
* Register callback actions for specific events
-Plugins are nothing more than Django applications using a specific
-structure. The ``__init__.py`` file contains a complete description of
-the plugin:
+Plugins are nothing more than Django applications with an extra piece
+of code that integrates them into Modoboa. Usually, the ``__init__.py`` file
+will contain a complete description of the plugin:
* Admin and user parameters
* Observed events
@@ -29,52 +29,49 @@ how you can create your own plugin.
Adding a custom plugin
======================
-All Modoboa plugins must be located inside the ``extensions``
-directory. To create a new plugin, execute the following steps:
+To create a new plugin, just start a new django application like
+this (into modoboa's directory)::
-* Run ``python manage.py startapp`` to get some basefiles for your plugin
-* Move the resulting directory inside the ``extensions`` one
+ $ python manage.py startapp
-The ``__init__.py`` file created inside your module's directory must
-follow a specific structure in order to be interpreted by Modoboa. The
-following functions are mandatory::
+Then, you need to register this application using the provided
+API. Just copy/paste the following example into the *__init__.py* file
+of the future extension::
- def init():
- """This function is called when the extension is activated.
- """
- pass
+ from modoboa.extensions import ModoExtension, exts_pool
+
+ class MyExtension(ModoExtension):
+ name = "myext"
+ label = "My Extension"
+ version = "0.1"
+ description = "A description"
+ url = "myext_root_location" # optional, name is used if not defined
+
+ def init(self):
+ """This method is called when the extension is activated.
+ """
+ pass
+
+ def load(self):
+ """This method is called when Modoboa loads available and activated plugins.
- def load():
- """This function is called when Modoboa loads available and activated plugins.
+ Declare parameters and register events here.
+ """
+ pass
+
+ def destroy(self):
+ """This function is called when a plugin is disabled from the interface.
+
+ Unregister parameters and events here.
+ """
+ pass
- Declare parameters and register events here.
- """
- pass
+ exts_pool.register_extension(MyExtension)
- def destroy():
- """This function is called when a plugin is disabled from the interface.
-
- Unregister parameters and events here.
- """
- pass
-
- def infos():
- """This function is used to populate the plugins list
- available in the administration panel.
-
- It must return a dictionnary containing at least three
- keys : "name", "version", "description"
- """
- return {
- "name" : "Example plugin",
- "version" : "1.0",
- "description" : "Example description"
- }
-
-Once you have filled ``__init__.py``, simply add your plugin's name to
-the ``INSTALLED_APPS`` variable located inside ``settings.py``. (use
-the same format as other plugins). Eventually, run ``python manage.py
-syncdb`` if your plugin provides custom tables.
+Once done, simply add your plugin's module name to the
+``INSTALLED_APPS`` variable located inside *settings.py*. Optionaly,
+run ``python manage.py syncdb`` if your plugin provides custom tables
+and ``python manage.py collectstatic`` to update static files.
Events
======
diff --git a/urls.py b/urls.py
index b35698809..835e16190 100644
--- a/urls.py
+++ b/urls.py
@@ -20,15 +20,14 @@ urlpatterns = patterns('',
(r'^accounts/logout/$', 'modoboa.auth.views.dologout'),
(r'^jsi18n/$', 'django.views.i18n.javascript_catalog',
{'packages': ('modoboa',),}),
-# *loadextensions(prefix)
*exts_pool.load_all(prefix)
)
if settings.DEBUG:
urlpatterns += patterns(
- '',
- (r'^static/(?P.*)$', 'django.views.static.serve',
- {'document_root': settings.MEDIA_ROOT})
+ url(r'^media/(?P.*)$', 'django.views.static.serve',
+ {'document_root': settings.MEDIA_ROOT, 'show_indexes' : True}),
+ url(r'', include('django.contrib.staticfiles.urls')),
)