API

Interfaces/Implementations

gdaps.api.Interface(cls) Iterable

Decorator for classes that are interfaces.

Declare an interface using the @Interface decorator, optionally add attributes/methods to that class:

@Interface
class IFooInterface:
    def do_something(self):
        pass

You can choose whatever name you want for your interfaces, but we recommend you start the name with a capital “I”. Read more about interfaces in the Interfaces section.

Plugin configuration and metadata

class gdaps.api.PluginMeta

Inner class of GDAPS plugins.

All GDAPS plugin AppConfig classes need to have an inner class named PluginMeta. This PluginMeta provides some basic attributes and methods that are needed when interacting with a plugin during its life cycle.

from django.utils.translation import gettext_lazy as _
from django.apps import AppConfig

class FooPluginConfig(AppConfig):

    class PluginMeta:
        # the plugin machine "name" is taken from the Appconfig, so no name here
        verbose_name = _('Foo Plugin')
        author = 'Me Personally'
        description = _('A foo plugin')
        hidden = false
        version = '1.0.0'
        compatibility = "myproject.core>=2.3.0"

Note

If PluginMeta is missing, the plugin is not recognized by GDAPS.

author = 'Me, myself and Irene'

The author of the plugin. Not translatable.

author_email = 'me@example.com'

The email address of the author

category = 'GDAPS'

A free-text category where your plugin belongs to. This can be used in your application to group plugins.

compatibility = 'gdaps>=1.0.0'

A string containing one or more other plugins that this plugin is known being compatible with, e.g. “myproject.core>=1.0.0<2.0.0” - meaning: This plugin is compatible with myplugin.core from version 1.0.0 to 1.x - v2.0 and above is incompatible.

Note

Work In Progress.

description = ''

A longer text to describe the plugin.

hidden = False

A boolean value whether the plugin should be hidden. False by default.

initialize()

Callback to initialize the plugin.

This method is optional. It is called and run at Django start once. If your plugin needs to make some initial checks, do them here, but make them quick, as they slow down Django’s start.

install()

Callback to setup the plugin for the first time.

This method is optional. If your plugin needs to install some data into the database at the first run, you can provide this method to PluginMeta. It will be called when manage.py syncplugins is called and the plugin is run, but only for the first time.

An example would be installing some fixtures, or providing a message to the user.

verbose_name = 'My special plugin'

The verbose name, as shown to the user

version = '1.0.0'

The version of the plugin, following Semantic Versioning. This is used for dependency checking as well, see compatibility.

class gdaps.api.PluginConfig(*args: Any, **kwargs: Any)

Convenience class for GDAPS plugins to inherit from.

While it is not strictly necessary to inherit from this class - duck typing is ok - it simplifies the type suggestions and autocompletion of IDEs like PyCharm, as PluginMeta is already declared here.

PluginManager

class gdaps.pluginmanager.PluginManager

A Generic Django Plugin Manager that finds Django app plugins in a plugins folder or setuptools entry points and loads them dynamically.

It provides a couple of methods to interaft with plugins, load submodules of all available plugins dynamically, or get a list of enabled plugins. Don’t instantiate a PluginManager directly, just use its static and class methods directly.

classmethod alter_installed_apps(installed_apps: list[str], group: str) None

Lets plugins update INSTALLED_APPS and add their own apps to it, in arbitrary order.

Call this method directly after your settings.INSTALLED_APPS declaration.

classmethod find_plugins(group: str) List[str]

Finds plugins from setuptools entry points.

This function is supposed to be called in settings.py after the INSTALLED_APPS variable. Therefore it can not use global variables from settings, to prevent circle imports.

Parameters

group – a dotted path where to find plugin apps. This is used as ‘group’ for setuptools’ entry points.

Returns

A list of dotted app_names, which can be appended to INSTALLED_APPS.

classmethod load_plugin_submodule(submodule: str, mandatory=False) list

Search plugin apps for specific submodules and load them.

Parameters
  • submodule – the dotted name of the Django app’s submodule to import. This package must be a submodule of the plugin’s namespace, e.g. “schema” - then [“<main>.core.schema”, “<main>.laboratory.schema”] etc. will be found and imported.

  • mandatory – If set to True, each found plugin _must_ contain the given submodule. If any installed plugin doesn’t have it, a PluginError is raised.

Returns

a list of module objects that have been successfully imported.

static orphaned_plugins() django.db.models.QuerySet

Returns a list of GdapsPlugin models that have no disk representance any more.

Note

This method needs Django’s ORM to be running.

classmethod plugin_path() str

Returns the absolute path where application plugins live.

This is basically the Django root + the dotted entry point. CAVE: this is not callable from within the settings.py file.

static plugins(skip_disabled: bool = False) List[PluginConfig]

Returns a list of AppConfig classes that are GDAPS plugins.

This method basically checks for the presence of a PluginMeta attribute within the AppConfig of all apps and returns a list of apps containing it. :param skip_disabled: If True, skips disabled plugins and only returns enabled ones. Defaults to False.

classmethod router() Union[SimpleRouter, DefaultRouter]

Loads all plugins’ urls.py and collects their routers into one.

Returns

a list of routers that can be merged with the global router.

static urlpatterns() list

Loads all plugins’ urls.py and collects their urlpatterns.

This is maybe not the best approach, but it allows plugins to have “global” URLs, and not only namespaced, and it is flexible

Returns

a list of urlpatterns that can be merged with the global urls.urlpattern.

Templates

class gdaps.api.interfaces.ITemplatePluginMixin

A mixin that can be inherited from to build renderable plugins.

Create an interface that inherits from ITemplatePluginMixin. Each implementation must either have a template (direct string HTML template, for short ones) or template_name (which points to the template to render).

You can add fixed context, or override get_plugin_context which receives the context of the view the plugin is rendered in.

In your template, use ` {% load gdaps %} <ul class="alerts"> {% render_plugin IMyListItem %} </ul> ` in your template anywhere, and all of your implementations are rendered, one after each other, in a line. Each plugin can come from another app. You can change the order of the rendering using the weight attribute.

context: dict = {}
get_plugin_context(context: django.template.context.Context) django.template.context.Context

Override this method to add custom context to the plugin.

Parameters

context – the context where the plugin is rendered in. You can update it with own values, and return it. The return variable of this function will be the context of the rendered plugin. So if you don’t update the passed context, but just return a new one, the plugin will not get access to the global context.

Per default, it merges the plugin’s context attribute into the given global context.

template: str = ''
template_name: str = ''
weight = 0

Helper functions

gdaps.api.require_app(app_config: django.apps.AppConfig, required_app_name: str) None

Helper function for AppConfig.ready() - checks if an app is installed.

An ImproperlyConfigured Exception is raised if the required app is not present.

Parameters
  • app_config – the AppConfig which requires another app. usually use self here when called from AppConfig.ready()

  • required_app_name – the required app name.