start to rewrite the poll-api
This commit is contained in:
parent
a54ff100d1
commit
0957de83a9
@ -137,29 +137,7 @@
|
||||
</td>
|
||||
{% if perms.agenda.can_manage_agenda %}
|
||||
<td>
|
||||
{% ifequal item.type 'ItemApplication' %}
|
||||
<a href="{% url application_view item.cast.application.id %}">{% trans "Application" %} {{ item.cast.application.number }}</a>
|
||||
{% endifequal %}
|
||||
|
||||
{% ifequal item.type 'ItemPoll' %}
|
||||
{% if item.cast.poll.application %}
|
||||
<a href="{% url poll_view item.cast.poll.id %}">{% trans "Poll of Application" %}</a>
|
||||
{% endif %}
|
||||
{% if item.cast.poll.assignment %}
|
||||
<a href="{% url poll_view item.cast.poll.id %}">{% trans "Poll of Election" %}</a>
|
||||
{% endif %}
|
||||
{% endifequal %}
|
||||
|
||||
{% ifequal item.type 'ItemAssignment' %}
|
||||
<a href="{% url assignment_view item.cast.assignment.id %}">{% trans "Election" %}</a>
|
||||
{% endifequal %}
|
||||
|
||||
{% ifequal item.type 'ItemText' %}
|
||||
Text
|
||||
{% endifequal %}
|
||||
{% if item.hidden %}
|
||||
({% trans 'hidden' %})
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
<td><span style="width: 1px;white-space: nowrap;">
|
||||
|
@ -23,6 +23,8 @@ from projector.models import Slide
|
||||
from participant.models import Profile
|
||||
from system.api import config_get
|
||||
from utils.utils import _propper_unicode
|
||||
from poll import ChoicePoll
|
||||
from poll.models import BaseOption, BasePoll
|
||||
|
||||
|
||||
class Application(models.Model, Slide):
|
||||
@ -410,23 +412,27 @@ class Application(models.Model, Slide):
|
||||
"""
|
||||
Generates a poll object for the application
|
||||
"""
|
||||
from poll.models import Poll
|
||||
poll = Poll(optiondecision=True, \
|
||||
application=self)
|
||||
poll = ApplicationPoll()
|
||||
poll.save()
|
||||
poll.add_option(self)
|
||||
poll.set_options([{'application': self}])
|
||||
self.writelog(_("Poll created"), user)
|
||||
return poll
|
||||
|
||||
@property
|
||||
def polls(self):
|
||||
#todo: return an query_set
|
||||
return [option.poll for option in self.applicationoption_set.all()]
|
||||
|
||||
@property
|
||||
def results(self):
|
||||
"""
|
||||
Return a list of voting results
|
||||
"""
|
||||
# TODO: This will propably not work
|
||||
results = []
|
||||
for poll in self.poll_set.all():
|
||||
for option in poll.options:
|
||||
if poll.votesinvalid != None and poll.votescast != None:
|
||||
for poll in self.polls:
|
||||
for option in poll.get_options():
|
||||
#if poll.votesinvalid != None and poll.votescast != None:
|
||||
results.append([option.yes, option.no, option.undesided, poll.votesinvalidf, poll.votescastf])
|
||||
return results
|
||||
|
||||
@ -484,3 +490,14 @@ class AVersion(models.Model):
|
||||
return self._aid
|
||||
|
||||
register_slidemodel(Application)
|
||||
|
||||
|
||||
class ApplicationOption(BaseOption):
|
||||
application = models.ForeignKey(Application)
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.application)
|
||||
|
||||
|
||||
class ApplicationPoll(BasePoll):
|
||||
option_class = ApplicationOption
|
||||
|
@ -16,8 +16,8 @@
|
||||
{% endif %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{%trans "Application No." %} {{ poll.application.number }} - {%trans "Vote" %}</h1>
|
||||
<h3>{{ poll.application.title }}</h3>
|
||||
<h1>{%trans "Application No." %} {{ application.number }} - {%trans "Vote" %}</h1>
|
||||
<h3>{{ application.title }}</h3>
|
||||
|
||||
<p>{%trans "Results of" %} {{ ballot }}. {%trans "Vote" %}</p>
|
||||
<i>-1 := {% trans 'majority' %}, -2 := {% trans 'undocumented' %}</i>
|
||||
@ -27,26 +27,12 @@
|
||||
<th>{% trans "Option" %}</th>
|
||||
<th>{% trans "Votes" %}</th>
|
||||
</tr>
|
||||
{% for value in forms.0 %}
|
||||
<tr>
|
||||
<td>{%trans "Yes" %}</td>
|
||||
<td>{{ options.0.form.yes.errors }}{{ options.0.form.yes }}</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td>{%trans "No" %}</label></td>
|
||||
<td>{{ options.0.form.no.errors }}{{ options.0.form.no }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{%trans "Abstentions" %}</td>
|
||||
<td>{{ options.0.form.undesided.errors }}{{ options.0.form.undesided }}</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td>{%trans "Invalid votes" %}</td>
|
||||
<td>{{ form.invalid.errors }}{{ form.invalid }}</td>
|
||||
</tr>
|
||||
<tr class="total">
|
||||
<td style="white-space: nowrap;"><b>{%trans "Votes cast" %}</b></td>
|
||||
<td>{{ form.votescast.errors }}{{ form.votescast }}</td>
|
||||
<td>{{ value.label }}</td>
|
||||
<td>{{ value.errors }}{{ value }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<p>
|
||||
<button class="button" type="submit">
|
||||
@ -55,11 +41,10 @@
|
||||
<button class="button" type="submit" name="apply">
|
||||
<span class="icon apply">{%trans 'Apply' %}</span>
|
||||
</button>
|
||||
<a href='{% url application_view poll.application.id %}'>
|
||||
<button class="button" type="button" onclick="window.location='{% url application_view poll.application.id %}'">
|
||||
<a href='{% url application_view application.id %}'>
|
||||
<button class="button" type="button" onclick="window.location='{% url application_view application.id %}'">
|
||||
<span class="icon cancel">{%trans 'Cancel' %}</span>
|
||||
</button>
|
||||
</a>
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
@ -47,7 +47,7 @@
|
||||
{% endfor %}
|
||||
|
||||
<h4>{% trans "Vote results" %}:</h4>
|
||||
{% with application.poll_set.all as polls %}
|
||||
{% with application.polls as polls %}
|
||||
{% if polls|length == 0 %}
|
||||
{% if perms.application.can_manage_application %}
|
||||
{% if "genpoll" in actions %}
|
||||
|
@ -11,6 +11,10 @@
|
||||
"""
|
||||
|
||||
from django.conf.urls.defaults import *
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from application.views import ViewPoll
|
||||
|
||||
|
||||
urlpatterns = patterns('application.views',
|
||||
url(r'^application/$', 'overview', \
|
||||
@ -77,8 +81,10 @@ urlpatterns = patterns('application.views',
|
||||
url(r'^application/poll/(?P<poll_id>\d+)/print$', 'print_application_poll', \
|
||||
name='print_application_poll'),
|
||||
|
||||
url(r'^application/poll/(?P<poll_id>\d+)$', 'view_poll', \
|
||||
name='application_poll_view'),
|
||||
url(r'^application/poll/(?P<poll_id>\d+)$',
|
||||
ViewPoll.as_view(),
|
||||
name='application_poll_view'
|
||||
),
|
||||
|
||||
url(r'^application/poll/(?P<poll_id>\d+)/del$', 'delete_poll', \
|
||||
name='application_poll_delete'),
|
||||
|
@ -23,14 +23,15 @@ from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ungettext
|
||||
from django.db import transaction
|
||||
|
||||
from openslides.agenda.models import Item
|
||||
from openslides.application.models import Application, AVersion
|
||||
from openslides.application.forms import ApplicationForm, \
|
||||
from agenda.models import Item
|
||||
from application.models import Application, AVersion, ApplicationPoll
|
||||
from application.forms import ApplicationForm, \
|
||||
ApplicationManagerForm, \
|
||||
ApplicationImportForm
|
||||
from openslides.participant.models import Profile
|
||||
from openslides.poll.models import Poll
|
||||
from openslides.poll.forms import OptionResultForm, PollForm
|
||||
|
||||
from poll.models import PollFormView
|
||||
|
||||
from openslides.utils.utils import template, permission_required, \
|
||||
render_to_forbitten, del_confirm_form, gen_confirm_form
|
||||
from openslides.utils.pdf import print_application, print_application_poll
|
||||
@ -92,7 +93,7 @@ def view(request, application_id, newest=False):
|
||||
'actions': actions,
|
||||
'min_supporters': int(config_get('application_min_supporters')),
|
||||
'version': version,
|
||||
'results': application.results
|
||||
#'results': application.results
|
||||
}
|
||||
|
||||
|
||||
@ -347,7 +348,7 @@ def gen_poll(request, application_id):
|
||||
poll = Application.objects.get(pk=application_id).gen_poll(user=request.user)
|
||||
messages.success(request, _("New vote was successfully created.") )
|
||||
except Application.DoesNotExist:
|
||||
pass
|
||||
pass # TODO: do not call poll after this excaption
|
||||
return redirect(reverse('application_poll_view', args=[poll.id]))
|
||||
|
||||
|
||||
@ -373,9 +374,9 @@ def view_poll(request, poll_id):
|
||||
"""
|
||||
view a poll for this application.
|
||||
"""
|
||||
poll = Poll.objects.get(pk=poll_id)
|
||||
ballot = poll.ballot
|
||||
options = poll.options
|
||||
poll = ApplicationPoll.objects.get(pk=poll_id)
|
||||
#ballot = poll.ballot
|
||||
options = poll.get_options()
|
||||
if request.user.has_perm('application.can_manage_application'):
|
||||
if request.method == 'POST':
|
||||
form = PollForm(request.POST, prefix="poll")
|
||||
@ -408,9 +409,27 @@ def view_poll(request, poll_id):
|
||||
'poll': poll,
|
||||
'form': form,
|
||||
'options': options,
|
||||
'ballot': ballot,
|
||||
#'ballot': ballot,
|
||||
}
|
||||
|
||||
|
||||
class ViewPoll(PollFormView):
|
||||
poll_class = ApplicationPoll
|
||||
vote_values = [_('yes'), _('no'), _('contained')]
|
||||
template_name = 'application/poll_view.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ViewPoll, self).get_context_data()
|
||||
self.application = self.poll.get_options()[0].application
|
||||
context['application'] = self.application
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
if not 'apply' in self.request.POST:
|
||||
return reverse('application_view', args=[self.application.id])
|
||||
return ''
|
||||
|
||||
|
||||
@permission_required('application.can_manage_application')
|
||||
def permit_version(request, aversion_id):
|
||||
aversion = AVersion.objects.get(pk=aversion_id)
|
||||
|
@ -17,8 +17,8 @@ from django.contrib.auth.decorators import login_required
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from openslides.agenda.models import Item
|
||||
from poll.models import Poll, Option
|
||||
from poll.forms import OptionResultForm, PollForm
|
||||
#from poll.models import Poll, Option
|
||||
#from poll.forms import OptionResultForm, PollForm
|
||||
from assignment.models import Assignment
|
||||
from assignment.forms import AssignmentForm, AssignmentRunForm
|
||||
from utils.utils import template, permission_required, gen_confirm_form, del_confirm_form, ajax_request
|
||||
|
@ -52,3 +52,4 @@ class Profile(models.Model):
|
||||
('can_see_participant', "Can see participant"),
|
||||
('can_manage_participant', "Can manage participant"),
|
||||
)
|
||||
|
||||
|
@ -0,0 +1,12 @@
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from models import PollFormView, BasePoll
|
||||
|
||||
|
||||
class DesicionPoll(PollFormView):
|
||||
vote_values = [_('yes'), _('no'), _('contained')]
|
||||
poll_class = BasePoll
|
||||
|
||||
|
||||
class ChoicePoll(PollFormView):
|
||||
poll_class = BasePoll
|
@ -12,185 +12,142 @@
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from application.models import Application
|
||||
from assignment.models import Assignment
|
||||
from participant.models import Profile
|
||||
from django import forms
|
||||
from django.views.generic import TemplateView
|
||||
from django.http import HttpResponseRedirect
|
||||
|
||||
|
||||
class Poll(models.Model):
|
||||
optiondecision = models.BooleanField(default=True, verbose_name = _("Poll of decision (yes, no, abstention)"))
|
||||
application = models.ForeignKey(Application, null=True, blank=True, verbose_name = _("Application"))
|
||||
assignment = models.ForeignKey(Assignment, null=True, blank=True, verbose_name = _("Election"))
|
||||
class OptionForm(forms.Form):
|
||||
def __init__(self, *args, **kwargs):
|
||||
extra = kwargs.pop('extra')
|
||||
formid = kwargs.pop('formid')
|
||||
kwargs['prefix'] = "option-%s" % formid
|
||||
super(OptionForm, self).__init__(*args, **kwargs)
|
||||
|
||||
for key, value in extra:
|
||||
self.fields[key] = forms.IntegerField(
|
||||
widget=forms.TextInput(attrs={'class': 'small-input'}),
|
||||
label=_(key),
|
||||
initial=value,
|
||||
)
|
||||
|
||||
class BaseOption(models.Model):
|
||||
poll = models.ForeignKey('BasePoll')
|
||||
|
||||
@property
|
||||
def votes(self):
|
||||
count = 0
|
||||
for vote in Vote.objects.filter(option=self):
|
||||
count += vote.weight
|
||||
return weight
|
||||
|
||||
|
||||
class TextOption(BaseOption):
|
||||
text = models.CharField(max_length=255)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.text
|
||||
|
||||
|
||||
class Vote(models.Model):
|
||||
option = models.ForeignKey(BaseOption)
|
||||
#profile = models.ForeignKey(Profile) # TODO: we need a person+ here
|
||||
weight = models.IntegerField(default=1)
|
||||
value = models.CharField(max_length=255, null=True)
|
||||
|
||||
|
||||
class BasePoll(models.Model):
|
||||
description = models.TextField(null=True, blank=True, verbose_name = _("Description"))
|
||||
votescast = models.IntegerField(null=True, blank=True, verbose_name = _("Votes cast"))
|
||||
votesinvalid = models.IntegerField(null=True, blank=True, verbose_name = _("Votes invalid"))
|
||||
published = models.BooleanField(default=False)
|
||||
|
||||
def add_option(self, option):
|
||||
self.save()
|
||||
optionc = Option()
|
||||
optionc.poll = self
|
||||
if isinstance(option, Application):
|
||||
optionc.application = option
|
||||
elif isinstance(option, Profile):
|
||||
optionc.user = option
|
||||
else:
|
||||
optionc.text = str(option)
|
||||
optionc.save()
|
||||
return optionc
|
||||
option_class = TextOption
|
||||
vote_values = [_('votes')]
|
||||
|
||||
@property
|
||||
def votescastf(self):
|
||||
if self.votescast == -2:
|
||||
return _('undocumented')
|
||||
elif self.votescast:
|
||||
return self.votescast
|
||||
return '0'
|
||||
|
||||
@property
|
||||
def votesinvalidf(self):
|
||||
if self.votesinvalid == -2:
|
||||
return _('undocumented')
|
||||
elif self.votesinvalid:
|
||||
if self.votescast > 0:
|
||||
percentage = round(float(self.votesinvalid) / float(self.votescast) * 100,1)
|
||||
invalid = "%s (%s %%)" % (str(self.votesinvalid), str(percentage))
|
||||
return invalid
|
||||
return self.votesinvalid
|
||||
return '0'
|
||||
|
||||
def has_vote(self):
|
||||
for option in self.options:
|
||||
if option.voteyes or option.voteno or option.voteundesided:
|
||||
return True
|
||||
return False
|
||||
def set_options(self, options_data):
|
||||
for option_data in options_data:
|
||||
option = self.option_class(**option_data)
|
||||
option.poll = self
|
||||
option.save()
|
||||
|
||||
def get_options(self):
|
||||
return self.option_set.all()
|
||||
return self.get_option_class().objects.filter(poll=self)
|
||||
|
||||
@property
|
||||
def options(self):
|
||||
return self.option_set.all()
|
||||
def get_option_class(self):
|
||||
return self.option_class
|
||||
|
||||
@property
|
||||
def options_values(self):
|
||||
return [option.value for option in self.options]
|
||||
def get_vote_values(self):
|
||||
return self.vote_values
|
||||
|
||||
def set_published(self, published=True):
|
||||
"""
|
||||
Changes the published-status of the poll.
|
||||
"""
|
||||
self.published = published
|
||||
self.save()
|
||||
|
||||
@property
|
||||
def count_ballots(self):
|
||||
if self.application:
|
||||
return Poll.objects.filter(application=self.application).count()
|
||||
if self.assignment:
|
||||
return Poll.objects.filter(assignment=self.assignment).count()
|
||||
return None
|
||||
|
||||
@property
|
||||
def ballot(self):
|
||||
if self.application:
|
||||
counter = 0
|
||||
for poll in Poll.objects.filter(application=self.application):
|
||||
counter = counter + 1
|
||||
if self == poll:
|
||||
return counter
|
||||
if self.assignment:
|
||||
counter = 0
|
||||
for poll in Poll.objects.filter(assignment=self.assignment):
|
||||
counter = counter + 1
|
||||
if self == poll:
|
||||
return counter
|
||||
return None
|
||||
|
||||
@models.permalink
|
||||
def get_absolute_url(self, link='view'):
|
||||
if self.application:
|
||||
if link == 'view':
|
||||
return ('application_poll_view', [str(self.id), 0])
|
||||
if link == 'delete':
|
||||
return ('application_poll_delete', [str(self.id)])
|
||||
if self.assignment:
|
||||
if link == 'view':
|
||||
return ('assignment_poll_view', [str(self.id), 0])
|
||||
if link == 'delete':
|
||||
return ('assignment_poll_delete', [str(self.id)])
|
||||
if link == 'view':
|
||||
return ('poll_view', [str(self.id)])
|
||||
if link == 'delete':
|
||||
return ('poll_delete', [str(self.id)])
|
||||
|
||||
def __unicode__(self):
|
||||
if self.application:
|
||||
return self.application.title
|
||||
if self.assignment:
|
||||
return self.assignment.name
|
||||
def set_form_values(self, option, data):
|
||||
for value in self.get_vote_values():
|
||||
try:
|
||||
vote = Vote.objects.filter(option=option).get(value=value)
|
||||
except Vote.DoesNotExist:
|
||||
vote = Vote(option=option, value=value)
|
||||
vote.weight = data[value]
|
||||
vote.save()
|
||||
|
||||
|
||||
class Option(models.Model):
|
||||
text = models.CharField(max_length=100, null=True, blank=True, verbose_name = _("Text"))
|
||||
user = models.ForeignKey(Profile, null=True, blank=True, verbose_name = _("Participant"))
|
||||
application = models.ForeignKey(Application, null=True, blank=True, verbose_name = _("Application"))
|
||||
poll = models.ForeignKey(Poll, verbose_name = _("Poll"))
|
||||
voteyes = models.IntegerField(null=True, blank=True)
|
||||
voteno = models.IntegerField(null=True, blank=True)
|
||||
voteundesided = models.IntegerField(null=True, blank=True)
|
||||
def get_form_values(self, option_id):
|
||||
values = []
|
||||
for value in self.get_vote_values():
|
||||
try:
|
||||
vote = Vote.objects.filter(option=option_id).get(value=value)
|
||||
weight = vote.weight
|
||||
except Vote.DoesNotExist:
|
||||
weight = None
|
||||
values.append((value, weight))
|
||||
return values
|
||||
|
||||
@property
|
||||
def yes(self):
|
||||
if self.voteyes == -1:
|
||||
return _('majority')
|
||||
if self.voteyes == -2:
|
||||
return _('undocumented')
|
||||
if self.voteyes:
|
||||
if self.poll.votescast > 0 and self.voteyes > 0:
|
||||
percentage = round(float(self.voteyes) / float(self.poll.votescast) * 100,1)
|
||||
return "%s (%s %%)" % (str(self.voteyes), str(percentage))
|
||||
return self.voteyes
|
||||
return '0'
|
||||
def get_vote_form(self, **kwargs):
|
||||
return OptionForm(extra=self.get_form_values(kwargs['formid']), **kwargs)
|
||||
|
||||
@property
|
||||
def no(self):
|
||||
if self.voteno == -1:
|
||||
return _('majority')
|
||||
if self.voteno == -2:
|
||||
return _('undocumented')
|
||||
if self.voteno:
|
||||
if self.poll.votescast > 0 and self.voteno > 0:
|
||||
percentage = round(float(self.voteno) / float(self.poll.votescast) * 100,1)
|
||||
return "%s (%s %%)" % (str(self.voteno), str(percentage))
|
||||
return self.voteno
|
||||
return '0'
|
||||
def get_vote_forms(self, **kwargs):
|
||||
forms = []
|
||||
for option in self.get_options():
|
||||
form = self.get_vote_form(formid=option.id, **kwargs)
|
||||
form.option = option
|
||||
forms.append(form)
|
||||
|
||||
@property
|
||||
def undesided(self):
|
||||
if self.voteundesided == -1:
|
||||
return _('majority')
|
||||
if self.voteundesided == -2:
|
||||
return _('undocumented')
|
||||
if self.voteundesided:
|
||||
if self.poll.votescast > 0 and self.voteundesided > 0:
|
||||
percentage = round(float(self.voteundesided) / float(self.poll.votescast) * 100,1)
|
||||
return "%s (%s %%)" % (str(self.voteundesided), str(percentage))
|
||||
return self.voteundesided
|
||||
return '0'
|
||||
return forms
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
if self.text != "" and self.text is not None:
|
||||
return self.text
|
||||
if self.user is not None:
|
||||
return self.user
|
||||
if self.application is not None:
|
||||
return self.application
|
||||
return None
|
||||
|
||||
def __unicode__(self):
|
||||
if self.value:
|
||||
return unicode(self.value)
|
||||
return _("No options")
|
||||
class PollFormView(TemplateView):
|
||||
template_name = 'poll/poll.html'
|
||||
poll_argument = 'poll_id'
|
||||
|
||||
def set_poll(self, poll_id):
|
||||
poll_id = poll_id
|
||||
self.poll = self.poll_class.objects.get(pk=poll_id)
|
||||
self.poll.vote_values = self.vote_values
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(PollFormView, self).get_context_data(**kwargs)
|
||||
self.set_poll(self.kwargs['poll_id'])
|
||||
context['poll'] = self.poll
|
||||
if not 'forms' in context:
|
||||
context['forms'] = context['poll'].get_vote_forms()
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return self.success_url
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
context = self.get_context_data(**kwargs)
|
||||
forms = self.poll.get_vote_forms(data=self.request.POST)
|
||||
error = False
|
||||
for form in forms:
|
||||
if not form.is_valid():
|
||||
error = True
|
||||
if error:
|
||||
return self.render_to_response(self.get_context_data(forms=forms))
|
||||
|
||||
for form in forms:
|
||||
data = {}
|
||||
for value in self.poll.vote_values:
|
||||
data[value] = form.cleaned_data[value]
|
||||
print data
|
||||
self.poll.set_form_values(form.option, data)
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
|
@ -36,7 +36,7 @@ from openslides.agenda.models import Item
|
||||
from openslides.agenda.api import children_list
|
||||
from openslides.application.models import Application
|
||||
from openslides.assignment.models import Assignment
|
||||
from openslides.poll.models import Poll, Option
|
||||
#from openslides.poll.models import Poll, Option
|
||||
from openslides.participant.models import Profile
|
||||
from openslides.system.api import config_get
|
||||
from openslides.settings import SITE_ROOT
|
||||
|
Loading…
Reference in New Issue
Block a user