diff options
Diffstat (limited to 'papillon/polls/views.py')
| -rw-r--r-- | papillon/polls/views.py | 491 | 
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) | 
