diff --git a/openslides/utils/dispatch.py b/openslides/utils/dispatch.py index 929bc1ff9..35291ba0b 100644 --- a/openslides/utils/dispatch.py +++ b/openslides/utils/dispatch.py @@ -8,13 +8,13 @@ class SignalConnectMetaClass(type): Classes must have a signal argument and a get_dispatch_uid classmethod. The signal argument must be the Django signal the class should be connected to. The get_dispatch_uid classmethod must return a unique - value for each child class and None for base classes which will not be - connected. + value for each child class and None for base classes because they will + not be connected to the signal. The classmethod get_all_objects is added as get_all classmethod to every class using this metaclass. Calling this on a base class or on child - classes will retrieve all connected children, on instance for each child - class. + classes will retrieve all connected children, one instance for each + child class. These instances will have a check_permission method which returns True by default. You can override this method to return False on runtime if @@ -24,6 +24,10 @@ class SignalConnectMetaClass(type): of the default_weight attribute which is 0 by default. You can override the attribute or the method to sort the children. + Don't forget to set up the __init__ method so that it is able to receive + wildcard keyword arguments (see example below). This is necessary + because of Django's signal API. + Example: class Base(object): @@ -76,7 +80,7 @@ def get_all_objects(cls, request): from all apps via signal. They are sorted using the get_default_weight method. Does not return objects where check_permission returns False. - Expects a request object. + Expects a django.http.HttpRequest object. This classmethod is added as get_all classmethod to every class using the SignalConnectMetaClass. diff --git a/openslides/utils/main_menu.py b/openslides/utils/main_menu.py index 89f9e10b6..49df3078a 100644 --- a/openslides/utils/main_menu.py +++ b/openslides/utils/main_menu.py @@ -17,8 +17,10 @@ class MainMenuEntry(object): __metaclass__ attribute (SignalConnectMetaClass) does the rest of the magic. - For the appearance there are some optional attributes like - permission_required, default_weight, stylesheets and javascript_files. + For the appearance there are some optional attributes and methods like + permission_required, default_weight, stylesheets, javascript_files, + check_permission, get_url, get_default_weight, get_icon_css_class, + get_stylesheets and get_javascript_files. """ __metaclass__ = SignalConnectMetaClass signal = Signal(providing_args=['request']) diff --git a/openslides/utils/personal_info.py b/openslides/utils/personal_info.py index c7f6a47d4..8075c6f0d 100644 --- a/openslides/utils/personal_info.py +++ b/openslides/utils/personal_info.py @@ -7,12 +7,14 @@ from .dispatch import SignalConnectMetaClass class PersonalInfo(object): """ - Base class for a personal info collection for the personal info widget. + Base class for a personal info collection for the personal info widget + on the dashboard. Every app which wants to add info has to create a class subclassing - from this base class. For the content the headline and default_weight - attribute and the get_queryset method have to be set. The __metaclass__ - attribute (SignalConnectMetaClass) does the rest of the magic. + from this base class. For the content the headline attribute, the + default_weight attribute and the get_queryset method have to be set. + The __metaclass__ attribute (SignalConnectMetaClass) does the rest of + the magic. """ __metaclass__ = SignalConnectMetaClass signal = Signal(providing_args=['request']) @@ -21,7 +23,8 @@ class PersonalInfo(object): def __init__(self, sender, request, **kwargs): """ - Initializes the personal info instance. This is done when the signal is sent. + Initializes the personal info instance. This is done when the + signal is sent. Only the required request argument is used. Because of Django's signal API, we have to take also a sender argument and wildcard keyword @@ -32,8 +35,8 @@ class PersonalInfo(object): @classmethod def get_dispatch_uid(cls): """ - Returns the classname as a unique string for each class. Returns None for - the base class so it will not be connected to the signal. + Returns the classname as a unique string for each class. Returns + None for the base class so it will not be connected to the signal. """ if not cls.__name__ == 'PersonalInfo': return cls.__name__ diff --git a/openslides/utils/widgets.py b/openslides/utils/widgets.py index f60d0b77e..620ed1a01 100644 --- a/openslides/utils/widgets.py +++ b/openslides/utils/widgets.py @@ -14,13 +14,16 @@ class Widget(object): Every app which wants to add widgets to the dashboard has to create a widget class subclassing from this base class. The name attribute has to - be set. The __metaclass__ attribute (SignalConnectMetaClass) does the - rest of the magic. + be set. It has to be unique. The __metaclass__ attribute + (SignalConnectMetaClass) does the rest of the magic. - For the appearance of the widget there are some optional attributes like - verbose_name, permission_required, default_column, default_weight, + For the appearance of the widget there are some attributes and methods + like verbose_name, permission_required, default_column, default_weight, default_active, template_name, context, icon_css_class, - more_link_pattern_name, stylesheets and javascript_files. + more_link_pattern_name, stylesheets, javascript_files, + get_verbose_name, check_permission, get_html, get_context_data, + get_icon_css_class, get_url_for_more, get_stylesheets and + get_javascript_files. Most of them are optional. """ __metaclass__ = SignalConnectMetaClass signal = Signal(providing_args=['request']) @@ -58,6 +61,9 @@ class Widget(object): """ Returns the name as a unique string for each class. Returns None for the base class so it will not be connected to the signal. + + This does not follow the example implementation of + SignalConnectMetaClass, so take care here. """ return cls.name