Added Django's application configuration.

Used customized AppConfig classes in openslides.core, openslides.account,
openslides.projector, openslides.agenda, openslides.motion, openslides.assignment,
openslides.users, openslides.mediafile, openslides.config.

Refactored loading of signals, template signals and slides.
This commit is contained in:
Norman Jäckel 2014-11-13 22:23:16 +01:00
parent 808aae597f
commit 4f04223e08
40 changed files with 288 additions and 125 deletions

View File

@ -7,9 +7,13 @@ http://openslides.org
Version 2.0.0 (unreleased)
==========================
- Changed supported Python version to >= 3.3
- Used Django 1.7 as lowest requirement
- Refactoring of the participant app. Now called 'users'
Other:
- Changed supported Python version to >= 3.3.
- Used Django 1.7 as lowest requirement.
- Refactoring of the participant app. Now called 'users'.
- Added Django's application configuration. Refactored loading of signals,
template signals and slides.
Version 1.6.1 (2014-12-08)

View File

@ -1 +1 @@
from . import widgets # noqa
default_app_config = 'openslides.account.apps.AccountAppConfig'

View File

@ -0,0 +1,10 @@
from django.apps import AppConfig
class AccountAppConfig(AppConfig):
name = 'openslides.account'
verbose_name = 'OpenSlides Account'
def ready(self):
# Load widget.
from . import widgets # noqa

View File

@ -1 +1 @@
from . import main_menu, personal_info, signals, slides, widgets # noqa
default_app_config = 'openslides.agenda.apps.AgendaAppConfig'

28
openslides/agenda/apps.py Normal file
View File

@ -0,0 +1,28 @@
from django.apps import AppConfig
class AgendaAppConfig(AppConfig):
name = 'openslides.agenda'
verbose_name = 'OpenSlides Agenda'
def ready(self):
# Load main menu entry, personal info and widgets.
# Do this by just importing all from these files.
from . import main_menu, personal_info, widgets # noqa
# Import all required stuff.
from django.db.models.signals import pre_delete
from openslides.config.signals import config_signal
from openslides.projector.api import register_slide
from openslides.projector.signals import projector_overlays
from .signals import agenda_list_of_speakers, setup_agenda_config, listen_to_related_object_delete_signal
from .slides import agenda_slide
# Connect signals.
config_signal.connect(setup_agenda_config, dispatch_uid='setup_agenda_config')
projector_overlays.connect(agenda_list_of_speakers, dispatch_uid='agenda_list_of_speakers')
pre_delete.connect(listen_to_related_object_delete_signal, dispatch_uid='agenda_listen_to_related_object_delete_signal')
# Register slides.
Item = self.get_model('Item')
register_slide('agenda', agenda_slide, Item)

View File

@ -1,6 +1,6 @@
import re
from ckeditor.widgets import CKEditorWidget
from ckeditor.widgets import CKEditorWidget
from django import forms
from django.utils.translation import ugettext_lazy
from mptt.forms import TreeNodeChoiceField

View File

@ -3,17 +3,13 @@ from datetime import datetime
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.config.api import config, ConfigCollection, ConfigVariable
from openslides.config.signals import config_signal
from openslides.projector.api import get_active_slide, get_active_object
from openslides.projector.projector import Overlay
from openslides.projector.signals import projector_overlays
from .models import Item
@ -27,10 +23,10 @@ def validate_start_time(value):
# TODO: Reinsert the datepicker scripts in the template
@receiver(config_signal, dispatch_uid='setup_agenda_config')
def setup_agenda_config(sender, **kwargs):
"""
Agenda config variables.
Receiver function to setup all agenda config variables. It is connected to
the signal openslides.config.signals.config_signal during app loading.
"""
# TODO: Insert validator for the format or use other field carefully.
agenda_start_event_date_time = ConfigVariable(
@ -94,10 +90,11 @@ def setup_agenda_config(sender, **kwargs):
'extra_javascript': extra_javascript})
@receiver(projector_overlays, dispatch_uid="agenda_list_of_speakers")
def agenda_list_of_speakers(sender, **kwargs):
"""
Receiver for the list of speaker overlay.
Receiver function to setup the list of speaker overlay. It is connected
to the signal openslides.projector.signals.projector_overlays during
app loading.
"""
name = 'agenda_speaker'
@ -141,10 +138,11 @@ def agenda_list_of_speakers(sender, **kwargs):
return Overlay(name, get_widget_html, get_projector_html)
@receiver(pre_delete)
def listen_to_related_object_delete_signal(sender, instance, **kwargs):
"""
Receiver to listen whether a related item has been deleted.
Receiver function to changed agenda items of a related items that is to
be deleted. It is connected to the signal
django.db.models.signals.pre_delete during app loading.
"""
if hasattr(instance, 'get_agenda_title'):
for item in Item.objects.filter(content_type=ContentType.objects.get_for_model(sender), object_id=instance.pk):

View File

@ -1,7 +1,7 @@
from django.template.loader import render_to_string
from openslides.config.api import config
from openslides.projector.api import get_projector_content, register_slide
from openslides.projector.api import get_projector_content
from .models import Item
@ -19,6 +19,8 @@ def agenda_slide(**kwargs):
If 'type' is 'summary', show a summary of all children of the item.
If 'type' is 'list_of_speakers', show the list of speakers for the item.
The function is registered during app loading.
"""
item_pk = kwargs.get('pk', None)
slide_type = kwargs.get('type', None)
@ -56,6 +58,3 @@ def agenda_slide(**kwargs):
context = {'item': item}
slide = render_to_string('agenda/item_slide.html', context)
return slide
register_slide('agenda', agenda_slide, Item)

View File

@ -1 +1 @@
# TODO: apploader
default_app_config = 'openslides.assignment.apps.AssignmentAppConfig'

View File

@ -0,0 +1,30 @@
from django.apps import AppConfig
class AssignmentAppConfig(AppConfig):
name = 'openslides.assignment'
verbose_name = 'OpenSlides Assignment'
def ready(self):
# Load main menu entry, personal info and widgets.
# Do this by just importing all from these files.
from . import main_menu, personal_info, widgets # noqa
# Import all required stuff.
from openslides.config.signals import config_signal
from openslides.projector.api import register_slide_model
from openslides.utils.signals import template_manipulation
from .signals import setup_assignment_config
from .template import add_assignment_stylesheets
# Connect signals.
config_signal.connect(setup_assignment_config, dispatch_uid='setup_assignment_config')
# Connect template signal.
template_manipulation.connect(add_assignment_stylesheets, dispatch_uid='add_assignment_stylesheets')
# Register slides.
Assignment = self.get_model('Assignment')
AssignmentPoll = self.get_model('AssignmentPoll')
register_slide_model(Assignment, 'assignment/slide.html')
register_slide_model(AssignmentPoll, 'assignment/assignmentpoll_slide.html')

View File

@ -342,7 +342,3 @@ class AssignmentPoll(SlideMixin, RelatedModelMixin, CollectDefaultVotesMixin,
def get_slide_context(self, **context):
return super(AssignmentPoll, self).get_slide_context(poll=self)
# TODO: use the app framework
from . import main_menu, personal_info, signals, slides, template, widgets # noqa

View File

@ -1,17 +1,16 @@
from django import forms
from django.dispatch import receiver
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.config.api import ConfigGroup, ConfigGroupedCollection, ConfigVariable
from openslides.config.signals import config_signal
from openslides.poll.models import PERCENT_BASE_CHOICES
@receiver(config_signal, dispatch_uid='setup_assignment_config')
def setup_assignment_config(sender, **kwargs):
"""
Assignment config variables.
Receiver function to setup all assignment config variables. It is
connected to the signal openslides.config.signals.config_signal during
app loading.
"""
# Ballot and ballot papers
assignment_poll_vote_values = ConfigVariable(

View File

@ -1,6 +0,0 @@
from openslides.projector.api import register_slide_model
from .models import Assignment, AssignmentPoll
register_slide_model(Assignment, 'assignment/slide.html')
register_slide_model(AssignmentPoll, 'assignment/assignmentpoll_slide.html')

View File

@ -1,11 +1,7 @@
from django.dispatch import receiver
from openslides.utils.signals import template_manipulation
@receiver(template_manipulation, dispatch_uid="add_assignment_stylesheets")
def add_assignment_stylesheets(sender, request, context, **kwargs):
"""
Adds the assignment.css to the context.
Receiver function to add the assignment.css to the context. It is
connected to the signal openslides.utils.signals.template_manipulation
during app loading.
"""
context['extra_stylefiles'].append('css/assignment.css')

View File

@ -1 +1 @@
from . import main_menu # noqa
default_app_config = 'openslides.config.apps.ConfigAppConfig'

11
openslides/config/apps.py Normal file
View File

@ -0,0 +1,11 @@
from django.apps import AppConfig
class ConfigAppConfig(AppConfig):
name = 'openslides.config'
verbose_name = 'OpenSlides Config'
def ready(self):
# Load main menu entry.
# Do this by just importing all from this file.
from . import main_menu # noqa

View File

@ -1 +1 @@
# TODO: apploading
default_app_config = 'openslides.core.apps.CoreAppConfig'

23
openslides/core/apps.py Normal file
View File

@ -0,0 +1,23 @@
from django.apps import AppConfig
class CoreAppConfig(AppConfig):
name = 'openslides.core'
verbose_name = 'OpenSlides Core'
def ready(self):
# Load main menu entry and widgets.
# Do this by just importing all from these files.
from . import main_menu, widgets # noqa
# Import all required stuff.
from openslides.config.signals import config_signal
from openslides.projector.api import register_slide_model
from .signals import setup_general_config
# Connect signals.
config_signal.connect(setup_general_config, dispatch_uid='setup_general_config')
# Register slides.
CustomSlide = self.get_model('CustomSlide')
register_slide_model(CustomSlide, 'core/customslide_slide.html')

View File

@ -44,7 +44,3 @@ class CustomSlide(SlideMixin, AbsoluteUrlMixin, models.Model):
else:
url = super(CustomSlide, self).get_absolute_url(link)
return url
# TODO: apploader
from . import main_menu, signals, slides, widgets # noqa

View File

@ -1,20 +1,20 @@
from django import forms
from django.dispatch import receiver, Signal
from django.dispatch import Signal
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.config.api import ConfigGroup, ConfigGroupedCollection, ConfigVariable
from openslides.config.signals import config_signal
from openslides.projector.api import update_projector
post_database_setup = Signal()
@receiver(config_signal, dispatch_uid='setup_general_config')
def setup_general_config(sender, **kwargs):
"""
General config variables for OpenSlides. They are grouped in 'Event',
'Welcome Widget' and 'System'.
Receiver function to setup general config variables for OpenSlides.
They are grouped in 'Event', 'Welcome Widget' and 'System'. The
function is connected to the signal
openslides.config.signals.config_signal during app loading.
"""
event_name = ConfigVariable(
name='event_name',

View File

@ -1,5 +0,0 @@
from openslides.projector.api import register_slide_model
from .models import CustomSlide
register_slide_model(CustomSlide, 'core/customslide_slide.html')

View File

@ -36,8 +36,11 @@ class CustonSlideWidget(Widget):
icon_css_class = 'icon-star'
def get_context_data(self, **context):
return super(CustonSlideWidget, self).get_context_data(
slides=CustomSlide.objects.all().order_by('weight'),
welcomepage_is_active=(
get_active_slide().get('callback', 'default') == 'default'),
**context)
"""
Adds custom slides and a flag whether the welcome page is active to
the context.
"""
context['slides'] = CustomSlide.objects.all().order_by('weight')
context['welcomepage_is_active'] = (
get_active_slide().get('callback', 'default') == 'default')
return super(CustonSlideWidget, self).get_context_data(**context)

View File

@ -1 +1 @@
from . import main_menu, slides, template, widgets # noqa
default_app_config = 'openslides.mediafile.apps.MediafileAppConfig'

View File

@ -0,0 +1,24 @@
from django.apps import AppConfig
class MediafileAppConfig(AppConfig):
name = 'openslides.mediafile'
verbose_name = 'OpenSlides Mediafile'
def ready(self):
# Load main menu entry and widgets.
# Do this by just importing all from these files.
from . import main_menu, widgets # noqa
# Import all required stuff.
from openslides.projector.api import register_slide
from openslides.utils.signals import template_manipulation
from .slides import mediafile_presentation_as_slide
from .template import add_mediafile_stylesheets
# Connect template signal.
template_manipulation.connect(add_mediafile_stylesheets, dispatch_uid='add_mediafile_stylesheets')
# Register slides.
Mediafile = self.get_model('Mediafile')
register_slide('mediafile', mediafile_presentation_as_slide, Mediafile)

View File

@ -1,9 +1,7 @@
#!/usr/bin/env python
from django.template.loader import render_to_string
from openslides.config.api import config
from openslides.projector.api import register_slide, SlideError
from openslides.projector.api import SlideError
from .models import Mediafile
@ -13,6 +11,8 @@ def mediafile_presentation_as_slide(**kwargs):
Return the html code for a presentation of a Mediafile.
At the moment, only the presentation of pdfs is supported.
The function is registered during app loading.
"""
file_pk = kwargs.get('pk', None)
page_num = kwargs.get('page_num', 1)
@ -27,6 +27,3 @@ def mediafile_presentation_as_slide(**kwargs):
context = {'pdf': pdf, 'page_num': page_num,
'fullscreen': config['pdf_fullscreen']}
return render_to_string('mediafile/presentation_slide.html', context)
register_slide('mediafile', mediafile_presentation_as_slide, Mediafile)

View File

@ -1,11 +1,7 @@
from django.dispatch import receiver
from openslides.utils.signals import template_manipulation
@receiver(template_manipulation, dispatch_uid="add_mediafile_stylesheets")
def add_mediafile_stylesheets(sender, request, context, **kwargs):
"""
Adds the mediafile.css to the context.
Receiver function to add the mediafile.css to the context. It is
connected to the signal openslides.utils.signals.template_manipulation
during app loading.
"""
context['extra_stylefiles'].append('css/mediafile.css')

View File

@ -1 +1 @@
# TODO: Apploading
default_app_config = 'openslides.motion.apps.MotionAppConfig'

27
openslides/motion/apps.py Normal file
View File

@ -0,0 +1,27 @@
from django.apps import AppConfig
class MotionAppConfig(AppConfig):
name = 'openslides.motion'
verbose_name = 'OpenSlides Motion'
def ready(self):
# Load main menu entry, personal info and widgets.
# Do this by just importing all from these files.
from . import main_menu, personal_info, widgets # noqa
# Import all required stuff.
from openslides.config.signals import config_signal
from openslides.core.signals import post_database_setup
from openslides.projector.api import register_slide_model
from .signals import create_builtin_workflows, setup_motion_config
# Connect signals.
config_signal.connect(setup_motion_config, dispatch_uid='setup_motion_config')
post_database_setup.connect(create_builtin_workflows, dispatch_uid='motion_create_builtin_workflows')
# Register slides.
Motion = self.get_model('Motion')
MotionPoll = self.get_model('MotionPoll')
register_slide_model(Motion, 'motion/slide.html')
register_slide_model(MotionPoll, 'motion/motionpoll_slide.html')

View File

@ -852,7 +852,3 @@ class Workflow(models.Model):
raise WorkflowError(
'%s can not be first state of %s because it '
'does not belong to it.' % (self.first_state, self))
# TODO: Apploading
from . import main_menu, personal_info, signals, slides, widgets # noqa

View File

@ -1,20 +1,17 @@
from django import forms
from django.dispatch import receiver
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.config.api import ConfigGroup, ConfigGroupedCollection, ConfigVariable
from openslides.config.signals import config_signal
from openslides.core.signals import post_database_setup
from openslides.poll.models import PERCENT_BASE_CHOICES
from .models import State, Workflow
@receiver(config_signal, dispatch_uid='setup_motion_config')
def setup_motion_config(sender, **kwargs):
"""
Motion config variables.
Receiver function to setup all motion config variables. It is connected to
the signal openslides.config.signals.config_signal during app loading.
"""
# General
motion_workflow = ConfigVariable(
@ -149,10 +146,11 @@ def setup_motion_config(sender, **kwargs):
groups=(group_general, group_supporters, group_ballot_papers, group_pdf))
@receiver(post_database_setup, dispatch_uid='motion_create_builtin_workflows')
def create_builtin_workflows(sender, **kwargs):
"""
Creates a simple and a complex workflow.
Receiver function to create a simple and a complex workflow. It is
connected to the signal openslides.core.signals.post_database_setup
during app loading.
"""
workflow_1, created = Workflow.objects.get_or_create(name=ugettext_noop('Simple Workflow'))
if created:

View File

@ -1,6 +0,0 @@
from openslides.projector.api import register_slide_model
from .models import Motion, MotionPoll
register_slide_model(Motion, 'motion/slide.html')
register_slide_model(MotionPoll, 'motion/motionpoll_slide.html')

View File

@ -0,0 +1,2 @@
# This app uses Django's base AppConfig class so the variable
# default_app_config is not defined.

View File

@ -1 +1 @@
from . import signals, widgets # noqa
default_app_config = 'openslides.projector.apps.ProjectorAppConfig'

View File

@ -0,0 +1,23 @@
from django.apps import AppConfig
class ProjectorAppConfig(AppConfig):
name = 'openslides.projector'
verbose_name = 'OpenSlides Projector'
def ready(self):
# Load widgets.
# Do this by just importing all from this file.
from . import widgets # noqa
# Import all required stuff.
from openslides.config.signals import config_signal
from .signals import (
countdown, projector_clock, projector_overlays,
projector_overlay_message, setup_projector_config)
# Connect signals.
config_signal.connect(setup_projector_config, dispatch_uid='setup_projector_config')
projector_overlays.connect(countdown, dispatch_uid="projector_countdown")
projector_overlays.connect(projector_overlay_message, dispatch_uid="projector_overlay_message")
projector_overlays.connect(projector_clock, dispatch_uid="projector_clock")

View File

@ -1,6 +1,5 @@
import warnings
from openslides.config.api import config
from .exceptions import ProjectorExceptionWarning

View File

@ -2,23 +2,22 @@ from time import time
from django.contrib.staticfiles.templatetags.staticfiles import static
from django.core.context_processors import csrf
from django.dispatch import receiver, Signal
from django.dispatch import Signal
from django.template.loader import render_to_string
from django.utils.datastructures import SortedDict
from openslides.config.api import config, ConfigCollection, ConfigVariable
from openslides.config.signals import config_signal
from .projector import Overlay
projector_overlays = Signal(providing_args=['request'])
@receiver(config_signal, dispatch_uid='setup_projector_config')
def setup_projector_config(sender, **kwargs):
"""
Projector config variables for OpenSlides. They are not shown on a
config view.
Receiver function to setup all projector config variables. They are not
shown on a config view. The function is connected to the signal
openslides.config.signals.config_signal during app loading.
"""
# The active slide. The config-value is a dictonary with at least the entry
# 'callback'.
@ -75,10 +74,10 @@ def setup_projector_config(sender, **kwargs):
projector_pdf_fullscreen))
@receiver(projector_overlays, dispatch_uid="projector_countdown")
def countdown(sender, **kwargs):
"""
Receiver for the countdown.
Receiver function for the projector countdown. The function is
connected to the signal projector_overlays during app loading.
"""
name = 'projector_countdown'
request = kwargs.get('request', None)
@ -116,11 +115,11 @@ def countdown(sender, **kwargs):
return Overlay(name, get_widget_html, get_projector_html, get_projector_js)
@receiver(projector_overlays, dispatch_uid="projector_overlay_message")
def projector_overlay_message(sender, **kwargs):
"""
Receiver to show the overlay_message on the projector or the form in the
overlay-widget on the dashboard.
Receiver function to show the overlay_message on the projector or the
form in the overlay-widget on the dashboard. The function is connected
to the signal projector_overlays during app loading.
"""
name = 'projector_message'
request = kwargs.get('request', None)
@ -143,10 +142,10 @@ def projector_overlay_message(sender, **kwargs):
return Overlay(name, get_widget_html, get_projector_html)
@receiver(projector_overlays, dispatch_uid="projector_clock")
def projector_clock(sender, **kwargs):
"""
Receiver to show the clock on the projector.
Receiver function to show the clock on the projector. The function is
connected to the signal projector_overlays during app loading.
"""
name = 'projector_clock'

View File

@ -1 +1 @@
from . import main_menu, signals, slides, widgets # noqa
default_app_config = 'openslides.users.apps.UsersAppConfig'

29
openslides/users/apps.py Normal file
View File

@ -0,0 +1,29 @@
from django.apps import AppConfig
class UsersAppConfig(AppConfig):
name = 'openslides.users'
verbose_name = 'OpenSlides Users'
def ready(self):
# Load main menu entry and widgets.
# Do this by just importing all from these files.
from . import main_menu, widgets # noqa
# Import all required stuff.
from django.db.models.signals import post_save
from openslides.config.signals import config_signal
from openslides.core.signals import post_database_setup
from openslides.projector.api import register_slide_model
from .signals import create_builtin_groups_and_admin, setup_users_config, user_post_save
# Load User model.
User = self.get_model('User')
# Connect signals.
config_signal.connect(setup_users_config, dispatch_uid='setup_users_config')
post_database_setup.connect(create_builtin_groups_and_admin, dispatch_uid='users_create_builtin_groups_and_admin')
post_save.connect(user_post_save, sender=User, dispatch_uid='users_user_post_save')
# Register slides.
register_slide_model(User, 'participant/user_slide.html')

View File

@ -1,23 +1,19 @@
from django import forms
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.dispatch import receiver
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
from django.db.models import signals
from openslides.config.api import ConfigGroup, ConfigGroupedCollection, ConfigVariable
from openslides.config.signals import config_signal
from openslides.core.signals import post_database_setup
from .api import create_or_reset_admin_user
from .models import Group, User
from .models import Group
@receiver(config_signal, dispatch_uid='setup_users_config')
def setup_users_config(sender, **kwargs):
"""
Participant config variables.
Receiver function to setup all users config variables. It is connected
to the signal openslides.config.signals.config_signal during app loading.
"""
# General
users_sort_users_by_first_name = ConfigVariable(
@ -108,14 +104,16 @@ def setup_users_config(sender, **kwargs):
groups=(group_general, group_pdf))
@receiver(post_database_setup, dispatch_uid='users_create_builtin_groups_and_admin')
def create_builtin_groups_and_admin(sender, **kwargs):
"""
Creates the buildin groups and the admin user.
Receiver function to builtin groups and the admin user.
Creates the builtin groups: Anonymous, Registered, Delegates and Staff.
Creates the builtin user: admin.
It is connected to the signal
openslides.core.signals.post_database_setup during app loading.
"""
# Check whether the group pks 1 to 4 are free
if Group.objects.filter(pk__in=range(1, 5)).exists():
@ -184,8 +182,12 @@ def create_builtin_groups_and_admin(sender, **kwargs):
create_or_reset_admin_user()
@receiver(signals.post_save, sender=User)
def user_post_save(sender, instance, *args, **kwargs):
"""
Receiver function to add a new user to the registered group. It is
connected to the signal django.db.models.signals.post_save during app
loading.
"""
if not kwargs['created']:
return

View File

@ -1,5 +0,0 @@
from openslides.projector.api import register_slide_model
from .models import User
register_slide_model(User, 'participant/user_slide.html')