This app provides a base class to easily realize django apps that allow other apps to register parts in it.
- Django >= 1.6
- From the pip repository:
pip install django-appregistration
- or directly from github:
pip install git+git://github.com/NB-Dev/django-apregistration.git
django-appregistration provides two base classes for the registration of modules from other apps:
MultiListPartRegistry
and SingleListPartRegistry
. While both have the same basic functionality, in the
MultiListPartRegistry
multiple distinct lists of objects can be collected, the SingleListPartRegistry
only
contains a single list.
To implement a ...PartRegistry
in your app, create a subclass of the ...PartRegistry
or your choice in a convenient
place in your application. There are some attributes you can overwrite in your Subclass:
-
part_class
(required): The (parent) class of the objects that are allowed to be inserted into your Registry -
call_function_subpath
(required): The subpath to the function that is to be called by the registry on load (details, see below) -
ignore_django_namespace
(default: True): If true, any app that starts withdjango.
in yourINSTALLED_APPS
will be ignored on load time.
To prevent arbitrary items to be inserted into your Registry the ...PartRegistry
classes check each added element to
be an instance of the class that is set as the part_class
attribute of the your Registry.
When the Registry tries to load elements from the INSTALLED_APPS
, it iterates over the apps and tries, for each to get
the sub module / function that is defined in the call_function_subpath
. It then checks if the retrieved object is
callable and calls it if so passing the Registry itself as only call parameter.
To register elements with the Registry you therefore need to implement the appropriate function at
call_function_subpath
in an app that is listed in the INSTALLED_APPS
. The implemented function then needs to call
the add_item
function on the passed registry.
To further simplify the usage of dynamic apps, the app provides a filter_available_apps
function that filters a list
of possible apps and returns only the ones that are available in the current installation. This allows for a highly
dynamic configuration of django projects by allowing certain apps to be installed selectively. Use it in your
settings.py
to dynamically add the available apps to your INSTALLED_APPS
from django_appregistration import filter_available_apps
INSTALLED_APPS = [
'imported_app1',
'imported_app2',
'imported_app3',
...
] + filter_available_apps(
'optional_app1',
'optional_app2',
'optional_app3',
...
)
Here is an implementation example with a Registry implemented in the extendable_app
app and an app extending_app
that extends the Registry
from django_appregistration import MultiListPartRegistry
class MyRegisterable(object):
pass
class MyRegistry(MultiListPartRegistry):
part_class = MyRegisterable
call_function_subpath = 'registerable.register'
def register(registry):
# import inside the function so that the import is only needed if the registry is used
# and the package is therefore available
from extendable_app.registry import MyRegisterable
registry.add_part('default', MyRegisterable())
registry.add_part('other', MyRegisterable())
Like this the extending_app
registers two parts when the registry is loaded, one in the list default
and one
in the list other
.
The objects can be retrieved like so:
from extendable_app.registry import MyRegistry
default_parts = MyRegistry.get('default') # retrieves the `default` list
other_parts = MyRegistry.get('other') # retrieves the `other` list
API documetation
The following functions are available:
Adds the part given by the part
parameter to the list with the name given by the list
parameter.
Returns the parts in the list with the name given by the list
parameter. The elements are sorted before they are
returned.
Can be overwritten to define a custom ordering of the parts. The default function simply returns the list unordered.
When called, the class is initialized and loads the available parts into its list cache. Does nothing if the load()
was already called. Is called automatically by the get()
function. There is no need to call it explicitly unless you
want to initialize the class before the first list is retrieved.
Resets the Registry to its initial state so that the parts will be reloaded the next time the load()
function is
called. Usually there is no need to call this as it only adds extra overhead when the parts need to be loaded again.
The following functions are additionally available:
Adds the part given by the part
parameter to the list.
Returns the parts in the list. The elements are sorted before they are returned.
The included tests can be run standalone by running the tests/runtests.py
script. You need to have Django and
mock installed for them to run. If you also want to run coverage, you need to install it before running the tests
- Fixing README heading levels
- Adding support for Django 1.10 and 1.11
- Adding the
filter_available_apps
function that checks a list of given apps for their availability.
- Bugfix: Also moved the
lock
and theloaded
attributes into the meta class
- Bugfix: Using a metaclass to separate the lists for each subclass of
MultiListPartRegistry
. Before each registry used the same list resulting in element mixtures if more than one registry was used
- Rename
Type
toList
in classes
- Initial implementation of
MultiTypePartRegistry
andSingleTypePartRegistry
This Project is maintained by Northbridge Development Konrad & Schneider GbR Softwareentwicklung.