polls: added multi-choices polls
This commit is contained in:
parent
b23fc15b6e
commit
d6512bb197
|
@ -1,5 +1,5 @@
|
|||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, SubmitField, TextAreaField
|
||||
from wtforms import StringField, SubmitField, TextAreaField, SelectField
|
||||
from wtforms.fields.html5 import DateTimeField
|
||||
from wtforms.validators import InputRequired, Optional
|
||||
|
||||
|
@ -19,6 +19,13 @@ class PollForm(FlaskForm):
|
|||
# TODO: add a validator to check if there is at least one choice
|
||||
]
|
||||
)
|
||||
type = SelectField(
|
||||
'Type',
|
||||
choices=[
|
||||
('simplepoll', 'Réponse unique'),
|
||||
('multiplepoll', 'Réponses multiples')
|
||||
]
|
||||
)
|
||||
start = DateTimeField(
|
||||
'Début',
|
||||
default=datetime.now(),
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
from app import db
|
||||
from app.models.poll import Poll, PollAnswer
|
||||
from collections import Counter
|
||||
from itertools import chain
|
||||
|
||||
|
||||
class MultiplePoll(Poll):
|
||||
"""Poll with many answers allowed"""
|
||||
|
||||
__tablename__ = 'multiplepoll'
|
||||
|
||||
# Names of templates
|
||||
template = 'multiplepoll.html'
|
||||
|
||||
__mapper_args__ = {
|
||||
'polymorphic_identity': __tablename__,
|
||||
}
|
||||
|
||||
def __init__(self, author, title, choices, **kwargs):
|
||||
choices = [Choice(i, t) for i, t in enumerate(choices)]
|
||||
super().__init__(author, title, choices, **kwargs)
|
||||
|
||||
# Mandatory methods
|
||||
def vote(self, user, request):
|
||||
answers_id = []
|
||||
for c in self.choices:
|
||||
if f"pollanswers-{c.id}" in request.form:
|
||||
answers_id.append(c.id)
|
||||
return PollAnswer(self, user, answers_id)
|
||||
|
||||
@property
|
||||
def results(self):
|
||||
values = {c: 0 for c in self.choices}
|
||||
counter = Counter(values)
|
||||
for a in self.answers:
|
||||
counter.update([self.choice_from_id(id) for id in a.answer])
|
||||
return counter
|
||||
|
||||
# Custom method
|
||||
def choice_from_id(self, id):
|
||||
for c in self.choices:
|
||||
if c.id == id:
|
||||
return c
|
||||
return None
|
||||
|
||||
class Choice():
|
||||
def __init__(self, id, title):
|
||||
self.id = id
|
||||
self.title = title
|
|
@ -3,6 +3,7 @@ from flask import abort, flash, redirect, request, url_for
|
|||
from flask_login import current_user
|
||||
|
||||
from app.models.polls.simple import SimplePoll
|
||||
from app.models.polls.multiple import MultiplePoll
|
||||
from app.forms.poll import PollForm
|
||||
from app.utils.render import render
|
||||
|
||||
|
@ -10,10 +11,14 @@ from app.utils.render import render
|
|||
def account_polls():
|
||||
form = PollForm()
|
||||
polls = current_user.polls
|
||||
polls_types = {
|
||||
'simplepoll': SimplePoll,
|
||||
'multiplepoll': MultiplePoll,
|
||||
}
|
||||
|
||||
if form.validate_on_submit():
|
||||
choices = list(filter(None, form.choices.data.split('\n')))
|
||||
p = SimplePoll(current_user, form.title.data, choices,
|
||||
p = polls_types[form.type.data](current_user, form.title.data, choices,
|
||||
start=form.start.data, end=form.end.data)
|
||||
db.session.add(p)
|
||||
db.session.commit()
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
<section class="form">
|
||||
<h1>Créer un sondage</h1>
|
||||
<form action="" method="post">
|
||||
{{ form.hidden_tag() }}
|
||||
<div>
|
||||
{{ form.title.label }}<br>
|
||||
{{ form.title(size=32) }}<br>
|
||||
|
@ -24,6 +23,13 @@
|
|||
<span class="msgerror">{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div>
|
||||
{{ form.type.label }}<br>
|
||||
{{ form.type }}<br>
|
||||
{% for error in form.type.errors %}
|
||||
<span style="color: red;">{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div>
|
||||
{{ form.start.label }}
|
||||
{{ form.start() }}
|
||||
|
@ -38,6 +44,7 @@
|
|||
<span class="msgerror">{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{{ form.hidden_tag() }}
|
||||
<div>{{ form.submit(class_="bg-ok") }}</div>
|
||||
</form>
|
||||
</section>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
{% macro choices(poll) %}
|
||||
<fieldset>
|
||||
{% for choice in poll.choices %}
|
||||
<input type="checkbox" id="poll{{ poll.id }}-{{ choice.id }}" name="pollanswers-{{ choice.id }}" value="{{ choice.id }}" />
|
||||
<label for="poll{{ poll.id }}-{{ choice.id }}">{{ choice.title }}</label><br/>
|
||||
{% endfor %}
|
||||
</fieldset>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro results(poll) %}
|
||||
<table>
|
||||
{% for choice, votes in poll.results.most_common() %}
|
||||
<tr>
|
||||
<td><label for="poll{{ poll.id }}-{{ choice.id }}">{{ choice.title }}</label></td>
|
||||
<td>
|
||||
<progress id="poll{{ poll.id }}-{{ choice.id }}" value="{{ votes }}" max="{{ len(poll.answers) }}"></progress>
|
||||
</td>
|
||||
<td>{{ votes }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th>Participations</th><th></th><th>{{ len(poll.answers) }}</th>
|
||||
</tr>
|
||||
</table>
|
||||
{% endmacro %}
|
Loading…
Reference in New Issue