Creating a plugin
It is possible to extend eventyay with custom Python code using the official plugin
API. Every plugin has to be implemented as an independent Django ‘app’ living
in its own python package installed like any other python module. There are also some
official plugins inside the eventyay/plugins/ directory of your eventyay installation.
The communication between eventyay and the plugins happens mostly using Django’s
signal dispatcher feature. The core modules of eventyay, eventyay.base,
eventyay.control and eventyay.presale expose a number of signals which are documented
on the next pages.
To create a new plugin, create a new python package which must be a valid Django app and must contain plugin metadata, as described below. There is some boilerplate that you will need for every plugin to get started. To save your time, we created a cookiecutter template that you can use like this:
$ pip install cookiecutter
$ cookiecutter https://github.com/fossasia/eventyay-plugin-cookiecutter
This will ask you some questions and then create a project folder for your plugin.
The following pages go into detail about the several types of plugins currently supported. While these instructions don’t assume that you know a lot about eventyay, they do assume that you have prior knowledge about Django (e.g. its view layer, how its ORM works, etc.).
Plugin metadata
The plugin metadata lives inside a eventyayPluginMeta class inside your app’s
configuration class. The metadata class must define the following attributes:
Attribute |
Type |
Description |
|---|---|---|
name |
string |
The human-readable name of your plugin |
author |
string |
Your name |
version |
string |
A human-readable version code of your plugin |
description |
string |
A more verbose description of what your plugin does. |
category |
string |
Category of a plugin. Either one of |
visible |
boolean (optional) |
|
restricted |
boolean (optional) |
|
compatibility |
string |
Specifier for compatible eventyay versions. |
A working example would be:
1try:
2 from eventyay.base.plugins import PluginConfig
3except ImportError:
4 raise RuntimeError("Please use eventyay 2.7 or above to run this plugin!")
5from django.utils.translation import gettext_lazy as _
6
7
8class PaypalApp(PluginConfig):
9 name = 'eventyay_paypal'
10 verbose_name = _("PayPal")
11
12 class EventyayPluginMeta:
13 name = _("PayPal")
14 author = _("the development team")
15 version = '1.0.0'
16 category = 'PAYMENT
17 visible = True
18 restricted = False
19 description = _("This plugin allows you to receive payments via PayPal")
20 compatibility = "eventyay>=2.7.0"
21
22
23default_app_config = 'eventyay_paypal.PaypalApp'
The AppConfig class may implement a property compatibility_errors, that checks
whether the eventyay installation meets all requirements of the plugin. If so,
it should contain None or an empty list, otherwise a list of strings containing
human-readable error messages. We recommend using the django.utils.functional.cached_property
decorator, as it might get called a lot. You can also implement compatibility_warnings,
those will be displayed but not block the plugin execution.
The AppConfig class may implement a method is_available(event) that checks if a plugin
is available for a specific event. If not, it will not be shown in the plugin list of that event.
Plugin registration
Somehow, eventyay needs to know that your plugin exists at all. For this purpose, we
make use of the entry point feature of setuptools. To register a plugin that lives
in a separate python package, your setup.py should contain something like this:
1setup(
2 args...,
3 entry_points="""
4[eventyay.plugin]
5eventyay_paypal=eventyay_paypal:eventyayPluginMeta
6"""
7)
This will automatically make eventyay discover this plugin as soon as it is installed e.g.
through pip. During development, you can just run python setup.py develop inside
your plugin source directory to make it discoverable.
Signals
The various components of eventyay define a number of signals which your plugin can
listen for. We will go into the details of the different signals in the following
pages. We suggest that you put your signal receivers into a signals submodule
of your plugin. You should extend your AppConfig (see above) by the following
method to make your receivers available:
1class PaypalApp(AppConfig):
2 name = 'eventyay_paypal'
3
4 def ready(self):
5 from . import signals # NOQA
You can optionally specify code that is executed when your plugin is activated for an event
in the installed method:
1class PaypalApp(AppConfig):
2 name = 'eventyay_paypal'
3
4 def installed(self, event):
5 pass # Your code here
Note that installed will not be called if the plugin is indirectly activated for an event
because the event is created with settings copied from another event.
Views
Your plugin may define custom views. If you put an urls submodule into your
plugin module, eventyay will automatically import it and include it into the root
URL configuration with the namespace plugins:<label>:, where <label> is
your Django app label.
Warning
If you define custom URLs and views, you are currently on your own with checking that the calling user is logged in, has appropriate permissions, etc. We plan on providing native support for this in a later version.