In any modern cms you usually have several components that will be registered and/or configured in every installed site. This registration and configurations parameters would be defined by superuser in merengue admin interface. All would be stored in database.
Example use cases:
Use case is: imagine we wants to implement a plugin registering system, with plugins configurable by developers. This is the current Merengue pluggable module.
First step is defining a registrable component. This is a Python class that must inherits from merengue.registry.items.RegistrableItem class:
from merengue.registry.items import RegistrableItem
class Plugin(RegistrableItem):
@classmethod
def get_category(cls):
return 'plugin'
The get_category method is needed, and say to Merengue what kind of objects you will register.
With this example, you have created a base class for all plugins. A plugin developer could declare his plugin with this fragment:
from merengue.pluggable import Plugin
class PluginConfig(Plugin):
name = 'fooplugin'
This is all you need to implement a registrable component.
Now we will consider we have implemented all pluggable system. Now we will learn to use registry for registering and unregistering objects.
For testing previous code fragment, make a fooplugin directory into plugins directory, with a __init__.py file inside it and a config.py file. In the last file, copy and paste previous code fragment.
How can I do plugin registering? With these sentences:
>>> from merengue.registry import register, is_registered, have_registered_items
>>> from plugins.fooplugin.config import PluginConfig
>>> have_registered_items(PluginConfig)
False
>>> reg_item = register(PluginConfig)
>>> have_registered_items(PluginConfig)
True
>>> item = reg_item.get_registry_item()
>>> is_registered(item)
True
Plugin autoregistering
Note your first call to is_registered returns True, this is because Merengue has plugin autoregistering activated and you have accessed to plugins admin view.
This sentences will register plugin by default in a RegisteredItem model in database. The RegisteredItem model definition is in merengue.registry.models module.
Note
Do not confusing RegisteredItem with RegistrableItem. The latter is not a Django model but an registrable object. The first is a model that store all RegistrableItem``s have been registered with ``merengue.registry.register function.
You can access to registered object with these sentences:
>>> from merengue.registry.models import RegisteredItem
>>> RegisteredItem.objects.all().values()
[{'class_name': u'PluginConfig', 'category': u'plugin', 'config': u'', 'id': 5, 'module': u'plugins.fooplugin.config'}]
>>> RegisteredItem.objects.by_item_class(PluginConfig)
[<RegisteredItem: PluginConfig>]
Let's look at this example:
from django.utils.translation import ugettext_lazy as _
from merengue.pluggable import Plugin
from merengue.registry import params
class PluginConfig(Plugin):
name = 'fooplugin'
config_params = [
params.Single(name='username', label=_('username'), default='pepe'),
params.List(name='friends', label=_('friends'),
default=['antonio', 'juan'],
choices=[('antonio', 'Antonio'),
('paco', 'Paco'),
('rosa', 'Rosa'),
('juan', 'Juan')]),
params.Single(name='season', label=_('season'),
choices=[('spring', _('Spring')),
('summer', _('Summer')),
('autumn', _('Autumn')),
('winter', _('Winter'))]),
]
Automatically, with this configuration, you can access to registered item in admin and will see and configure all parameters of this component:
If plugin developer want to access this configuration (remember, the configuration you customize in admin, no the default config_params for plugin), he would use these sentences:
>>> from merengue.registry import get_item
>>> plugin = get_item('plugins.fooplugin.config.PluginConfig')
>>> config = plugin.get_config()
>>> print config['friends'].get_value()
['paco', 'juan']
>>> print config['friends'].choices
[('antonio', 'Antonio'), ('paco', 'Paco'), ('rosa', 'Rosa'), ('juan', 'Juan')]
>>> print config['friends'].default
['antonio', 'juan']
>>> config['friends'].get_type()
'List'
If you register a registrable item, you also will save this configuration in database. See this example:
class PersonItem(RegistrableItem):
config_params = [
params.Bool(name='is_human', default=True),
params.Integer(name='age'),
params.List(name='friends', choices=('Juan', 'Luis', 'Pepe'))
]
And now an example use:
>>> reg_item = register(PersonItem)
>>> item = reg_item.get_registry_item()
>>> item.get_config()
{'is_human': <True, Bool>,
'age': <<class 'merengue.registry.params.NOT_PROVIDED'>, Integer>,
'friends': <<class 'merengue.registry.params.NOT_PROVIDED'>, List>}
>>> reg_item.config
{u'is_human': True}
>>> reg_item.config['age'] = 30
>>> reg_item.save()
>>> item.get_config()
{'is_human': <True, Bool>,
'age': <30, Integer>,
'friends': <<class 'merengue.registry.params.NOT_PROVIDED'>, List>}
You can define a registered item not actived by default:
class PersonItem(RegistrableItem):
active_by_default = False
When you register a item with active_by_default attribute to False will be included in the database but will not affect in the website until manager actives it in admin interface.
Sometimes you need to define a constrain to register only one item for every item class. This is named a singleton. In a Merengue plugin, its actions, panels and viewlets are singletons, but blocks not (because you can add two same blocks in your web).
To define a singleton you have to add a singleton=True in your registrable class definition. See this explanatory example:
class NonSingletonItem(RegistrableItem):
pass
class SingletonItem(RegistrableItem):
singleton = True
See what happen if I do some registering tasks:
>>> register(NonSingletonItem)
<RegisteredItem: NonSingletonItem>
>>> register(NonSingletonItem)
<RegisteredItem: NonSingletonItem>
>>> register(SingletonItem)
<RegisteredItem: SingletonItem>
>>> register(SingletonItem)
...
AlreadyRegistered: item class "<class 'fooplugin.SingletonItem'>" is already registered
>>> from merengue.registry import get_items, get_item
>>> get_item(SingletonItem)
<fooplugin.SingletonItem object at 0xaae482c>
>>> list(get_items(NonSingletonItem))
[<fooplugin.NonSingletonItem object at 0xad60f2c>,
<fooplugin.NonSingletonItem object at 0xad60e6c>]
>>> get_item(NonSingletonItem)
...
MultipleObjectsReturned: get() returned more than one RegisteredItem -- it returned 2! Lookup parameters were {}
Jun 17, 2011