summaryrefslogtreecommitdiff
path: root/papillon/polls/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'papillon/polls/views.py')
-rw-r--r--papillon/polls/views.py491
1 files changed, 491 insertions, 0 deletions
diff --git a/papillon/polls/views.py b/papillon/polls/views.py
new file mode 100644
index 0000000..e9ef572
--- /dev/null
+++ b/papillon/polls/views.py
@@ -0,0 +1,491 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2008 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+'''
+Views management
+'''
+
+from random import choice as random_choice
+import string
+import time
+from datetime import datetime
+
+from django.utils.translation import gettext_lazy as _
+from django.shortcuts import render_to_response
+from django.http import HttpResponseRedirect
+
+from papillon.settings import LANGUAGES, BASE_SITE
+from papillon.polls.models import Poll, PollUser, Choice, Voter, Vote, \
+ Category, Comment
+from papillon.polls.forms import CreatePollForm, AdminPollForm, ChoiceForm, \
+ DatedChoiceForm, CommentForm
+
+def getBaseResponse(request):
+ """Manage basic fields for the template
+ If not null the second argument returned is a redirection.
+ """
+ url = BASE_SITE
+ # setting the current language and available languages
+ if 'language' in request.GET:
+ if request.GET['language'] in [language[0] for language in LANGUAGES]:
+ request.session['django_language'] = request.GET['language']
+ return None, HttpResponseRedirect(request.path)
+ languages = []
+ for language_code, language_label in LANGUAGES:
+ languages.append((language_code, language_label))
+ return {'root_url':url, 'languages':languages}, None
+
+def index(request):
+ "Main page"
+ response_dct, redirect = getBaseResponse(request)
+ if redirect:
+ return redirect
+ response_dct['polls'] = Poll.objects.filter(public=True, category=None)
+ response_dct['categories'] = Category.objects.all()
+ error = ''
+ if 'bad_poll' in request.GET:
+ response_dct['error'] = _("The poll requested don't exist (anymore?)")
+ return render_to_response('main.html', response_dct)
+
+def category(request, category_id):
+ "Page for a category"
+ response_dct, redirect = getBaseResponse(request)
+ if redirect:
+ return redirect
+ category = Category.objects.get(id=int(category_id))
+ response_dct['category'] = category
+ response_dct['polls'] = Poll.objects.filter(public=True, category=category)
+ return render_to_response('category.html', response_dct)
+
+def create(request):
+ '''Creation of a poll.
+ '''
+ def genRandomURL():
+ "Generation of a random url"
+ url = ''
+ while not url or Poll.objects.filter(base_url=url).count() or\
+ Poll.objects.filter(admin_url=url).count():
+ url = ''
+ chars = string.letters + string.digits
+ for i in xrange(6):
+ url += random_choice(chars)
+ url += str(int(time.time()))
+ return url
+
+ response_dct, redirect = getBaseResponse(request)
+ if redirect:
+ return redirect
+
+ if request.method == 'POST':
+ form = CreatePollForm(request.POST)
+ if form.is_valid():
+ poll = form.save()
+ poll.admin_url = genRandomURL()
+ poll.base_url = genRandomURL()
+ poll.save()
+ return HttpResponseRedirect('%seditChoicesAdmin/%s/' % (
+ response_dct['root_url'], poll.admin_url))
+ else:
+ form = CreatePollForm()
+ response_dct['form'] = form
+ return render_to_response('create.html', response_dct)
+
+def edit(request, admin_url):
+ '''Edition of a poll.
+ '''
+ response_dct, redirect = getBaseResponse(request)
+ if redirect:
+ return redirect
+ try:
+ poll = Poll.objects.filter(admin_url=admin_url)[0]
+ except IndexError:
+ # if the poll don't exist redirect to the creation page
+ url = response_dct['root_url']
+ return HttpResponseRedirect('%screate' % (
+ response_dct['root_url']))
+ Form = AdminPollForm
+
+ if request.method == 'POST':
+ form = Form(request.POST, instance=poll)
+ if form.is_valid():
+ poll = form.save()
+ return HttpResponseRedirect('%sedit/%s/' % (
+ response_dct['root_url'], poll.admin_url))
+ else:
+ form = Form(instance=poll)
+ response_dct['form'] = form
+ response_dct['poll'] = poll
+ return render_to_response('edit.html', response_dct)
+
+def editChoicesAdmin(request, admin_url):
+ response_dct, redirect = getBaseResponse(request)
+ if redirect:
+ return redirect
+ try:
+ poll = Poll.objects.filter(admin_url=admin_url)[0]
+ except IndexError:
+ # if the poll don't exist redirect to the main page
+ url = "/".join(request.path.split('/')[:-2])
+ return response_dct, HttpResponseRedirect(url)
+ response_dct['poll'] = poll
+ return editChoices(request, response_dct, admin=True)
+
+def editChoicesUser(request, poll_url):
+ response_dct, redirect = getBaseResponse(request)
+ if redirect:
+ return redirect
+ try:
+ poll = Poll.objects.filter(base_url=poll_url)[0]
+ except IndexError:
+ poll = None
+ if not poll or not poll.opened_admin:
+ # if the poll don't exist redirect to the main page
+ url = "/".join(request.path.split('/')[:-2])
+ return HttpResponseRedirect(url)
+ response_dct['poll'] = poll
+ return editChoices(request, response_dct)
+
+def editChoices(request, response_dct, admin=False):
+ '''Edition of choices.
+ '''
+ poll = response_dct['poll']
+ tpl = 'editChoicesAdmin.html'
+ if not admin:
+ tpl = 'editChoicesUser.html'
+ Form = ChoiceForm
+ if poll.dated_choices:
+ Form = DatedChoiceForm
+ try:
+ order = Choice.objects.order_by('-order')[0].order
+ order += 1
+ except IndexError:
+ order = 0
+ form = Form(initial={'poll':poll.id, 'order':str(order)})
+
+ if request.method == 'POST':
+ # if a new choice is submitted
+ if 'add' in request.POST and request.POST['poll'] == str(poll.id):
+ f = Form(request.POST)
+ if f.is_valid():
+ choice = f.save()
+ poll.reorder()
+ else:
+ form = f
+ if admin and 'edit' in request.POST \
+ and request.POST['poll'] == str(poll.id):
+ try:
+ choice = Choice.objects.get(id=int(request.POST['edit']))
+ if choice.poll != poll:
+ raise ValueError
+ f = Form(request.POST, instance=choice)
+ if f.is_valid():
+ choice = f.save()
+ poll.reorder()
+ except (Choice.DoesNotExist, ValueError):
+ pass
+ if admin:
+ # check if a choice has been choosen for deletion
+ for key in request.POST:
+ if key.startswith('delete_') and request.POST[key]:
+ try:
+ choice = Choice.objects.get(id=int(key[len('delete_'):]))
+ if choice.poll != poll:
+ raise ValueError
+ Vote.objects.filter(choice=choice).delete()
+ choice.delete()
+ except (Choice.DoesNotExist, ValueError):
+ pass
+ # check if the order of a choice has to be changed
+ if admin and request.method == 'GET':
+ for key in request.GET:
+ try:
+ current_url = request.path.split('?')[0]
+ if 'up_choice' in key:
+ choice = Choice.objects.get(id=int(request.GET[key]))
+ if choice.poll != poll:
+ raise ValueError
+ choice.changeOrder(-1)
+ poll.reorder()
+ # redirect in order to avoid a change with a refresh
+ return HttpResponseRedirect(current_url)
+ if 'down_choice' in key:
+ choice = Choice.objects.get(id=int(request.GET[key]))
+ if choice.poll != poll:
+ raise ValueError
+ choice.changeOrder(1)
+ poll.reorder()
+ # redirect in order to avoid a change with a refresh
+ return HttpResponseRedirect(current_url)
+ except (ValueError, Choice.DoesNotExist):
+ pass
+ choices = Choice.objects.filter(poll=poll).order_by('order')
+ for choice in choices:
+ if admin and poll.dated_choices:
+ choice.name = choice.date
+ choice.form = Form(instance=choice)
+ response_dct['choices'] = choices
+ response_dct['form_new_choice'] = form
+ return render_to_response(tpl, response_dct)
+
+def poll(request, poll_url):
+ """Display a poll
+ poll_url is given to identify the poll. If '_' is in the poll_url the second
+ part of the url is the unix time given to highlight a particular vote
+ modification
+ """
+
+ def modifyVote(request, choices):
+ "Modify user's votes"
+ try:
+ voter = Voter.objects.filter(
+ id=int(request.POST['voter']))[0]
+ except (ValueError, IndexError):
+ return
+ # if no author_name is given deletion of associated votes and
+ # author
+ if not request.POST['author_name']:
+ # verify if the author can be deleted
+ delete_user = None
+ if not voter.user.password:
+ v = Voter.objects.filter(user=voter.user)
+ if len(v) == 1 and v[0] == voter:
+ delete_user = voter.user
+ for choice in choices:
+ v = Vote.objects.filter(voter=voter, choice=choice)
+ v.delete()
+ voter.delete()
+ if delete_user:
+ delete_user.delete()
+ return
+ # update the name
+ voter.user.name = request.POST['author_name']
+ voter.user.save()
+ # update the modification date
+ voter.save()
+ selected_choices = []
+ # set the selected choices
+ for key in request.POST:
+ # modify a one choice poll
+ if key == 'vote' and request.POST[key]:
+ try:
+ id = int(request.POST[key])
+ vote = Vote.objects.filter(id=id)[0]
+ if vote.choice not in choices:
+ # bad vote id : the associated choice has
+ # probably been deleted
+ vote.delete()
+ else:
+ vote.value = 1
+ vote.save()
+ selected_choices.append(vote.choice)
+ except (ValueError, IndexError):
+ # the vote don't exist anymore
+ pass
+ # modify an existing vote
+ if key.startswith('vote_') and request.POST[key]:
+ try:
+ id = int(key.split('_')[1])
+ vote = Vote.objects.filter(id=id)[0]
+ if vote.choice not in choices:
+ # bad vote id : the associated choice has
+ # probably been deleted
+ vote.delete()
+ else:
+ # try if a specific value is specified in the form
+ # like in balanced poll
+ try:
+ value = int(request.POST[key])
+ except ValueError:
+ value = 1
+ vote.value = value
+ vote.save()
+ selected_choices.append(vote.choice)
+ except (ValueError, IndexError):
+ # the vote don't exist anymore
+ pass
+ # update non selected choices
+ for choice in choices:
+ if choice not in selected_choices:
+ try:
+ v = Vote.objects.filter(voter=voter, choice=choice)[0]
+ v.value = 0
+ except IndexError:
+ # the vote don't exist with this choice : probably
+ # a new choice
+ v = Vote(voter=voter, choice=choice, value=0)
+ v.save()
+ def newComment(request, poll):
+ "Comment the poll"
+ if 'comment_author' not in request.POST \
+ or not request.POST['comment_author'] \
+ or not request.POST['comment']:
+ return
+ c = Comment(poll=poll, author_name=request.POST['comment_author'],
+ text=request.POST['comment'])
+ c.save()
+
+ def newVote(request, choices):
+ "Create new votes"
+ if not request.POST['author_name']:
+ return
+ author = PollUser(name=request.POST['author_name'])
+ author.save()
+ voter = Voter(user=author, poll=poll)
+ voter.save()
+ selected_choices = []
+
+ # set the selected choices
+ for key in request.POST:
+ # standard vote
+ if key.startswith('choice_') and request.POST[key]:
+ try:
+ id = int(key.split('_')[1])
+ choice = Choice.objects.filter(id=id)[0]
+ if choice not in choices:
+ raise ValueError
+ # try if a specific value is specified in the form
+ # like in balanced poll
+ try:
+ value = int(request.POST[key])
+ except ValueError:
+ value = 1
+ v = Vote(voter=voter, choice=choice, value=value)
+ v.save()
+ selected_choices.append(choice)
+ except (ValueError, IndexError):
+ # bad choice id : the choice has probably been deleted
+ pass
+ # one choice vote
+ if key == 'choice' and request.POST[key]:
+ try:
+ id = int(request.POST[key])
+ choice = Choice.objects.filter(id=id)[0]
+ if choice not in choices:
+ raise ValueError
+ v = Vote(voter=voter, choice=choice, value=1)
+ v.save()
+ selected_choices.append(choice)
+ except (ValueError, IndexError):
+ # bad choice id : the choice has probably been deleted
+ pass
+ # set non selected choices
+ for choice in choices:
+ if choice not in selected_choices:
+ v = Vote(voter=voter, choice=choice, value=0)
+ v.save()
+ # results can now be displayed
+ request.session['knowned_vote_' + poll.base_url] = 1
+ response_dct, redirect = getBaseResponse(request)
+ if redirect:
+ return redirect
+ highlight_vote_date = None
+ if '_' in poll_url:
+ url_spl = poll_url.split('_')
+ if len(url_spl) == 2:
+ poll_url, highlight_vote_date = url_spl
+ try:
+ highlight_vote_date = int(highlight_vote_date)
+ except ValueError:
+ highlight_vote_date = None
+ try:
+ poll = Poll.objects.filter(base_url=poll_url)[0]
+ except IndexError:
+ poll = None
+ choices = list(Choice.objects.filter(poll=poll))
+ # if the poll don't exist or if it has no choices the user is
+ # redirected to the main page
+ if not choices or not poll:
+ url = "/".join(request.path.split('/')[:-3])
+ url += "/?bad_poll=1"
+ return HttpResponseRedirect(url)
+
+ # a vote is submitted
+ if 'author_name' in request.POST and poll.open:
+ if 'voter' in request.POST:
+ # modification of an old vote
+ modifyVote(request, choices)
+ else:
+ newVote(request, choices)
+ # update the modification date of the poll
+ poll.save()
+ if 'comment' in request.POST and poll.open:
+ # comment posted
+ newComment(request, poll)
+
+ # 'voter' is in request.GET when the edit button is pushed
+ if 'voter' in request.GET and poll.open:
+ try:
+ response_dct['current_voter_id'] = int(request.GET['voter'])
+ except ValueError:
+ pass
+
+ response_dct.update({'poll':poll,
+ 'VOTE':Vote.VOTE,})
+ response_dct['base_url'] = "/".join(request.path.split('/')[:-2]) \
+ + '/%s/' % poll.base_url
+
+ # get voters and sum for each choice for this poll
+ voters = Voter.objects.filter(poll=poll)
+ choice_ids = [choice.id for choice in choices]
+ for voter in voters:
+ # highlight a voter
+ if time.mktime(voter.modification_date.timetuple()) \
+ == highlight_vote_date:
+ voter.highlight = True
+ voter.votes = voter.getVotes(choice_ids)
+ # initialize undefined vote
+ choice_vote_ids = [vote.choice.id for vote in voter.votes]
+ for choice in choices:
+ if choice.id not in choice_vote_ids:
+ vote = Vote(voter=voter, choice=choice, value=None)
+ vote.save()
+ idx = choices.index(choice)
+ voter.votes.insert(idx, vote)
+ sums = [choice.getSum(poll.type == 'B') for choice in choices]
+ vote_max = max(sums)
+ c_idx = 0
+ while c_idx < len(choices):
+ try:
+ c_idx = sums.index(vote_max, c_idx)
+ choices[c_idx].highlight = True
+ c_idx += 1
+ except ValueError:
+ c_idx = len(choices)
+ # set non-available choices if the limit is reached for a choice
+ response_dct['limit_set'] = None
+ for choice in choices:
+ if choice.limit:
+ response_dct['limit_set'] = True
+ if choice.limit and sums[choices.index(choice)] >= choice.limit:
+ choice.available = False
+ else:
+ choice.available = True
+ choice.save()
+ response_dct['voters'] = voters
+ response_dct['choices'] = choices
+ response_dct['comments'] = Comment.objects.filter(poll=poll)
+ # verify if vote's result has to be displayed
+ response_dct['hide_vote'] = poll.hide_choices
+ if poll.hide_choices:
+ if u'display_result' in request.GET:
+ request.session['knowned_vote_' + poll.base_url] = 1
+ if 'knowned_vote_' + poll.base_url in request.session:
+ response_dct['hide_vote'] = False
+ response_dct['form_comment'] = CommentForm()
+ return render_to_response('vote.html', response_dct)