diff options
Diffstat (limited to 'polls/views.py')
-rw-r--r-- | polls/views.py | 312 |
1 files changed, 203 insertions, 109 deletions
diff --git a/polls/views.py b/polls/views.py index 040a9b9..8bb8157 100644 --- a/polls/views.py +++ b/polls/views.py @@ -14,11 +14,13 @@ from django.http import HttpResponseRedirect from papillon.polls.models import Poll, PollUser, Choice, Vote def getBaseResponse(request): + "Get the root url in order to redirect to the main page" url = "/".join([request.META['HTTP_HOST'], request.path.split('/')[1], '']) return {'root_url':url} def index(request): + "Main page" response_dct = getBaseResponse(request) error = '' if 'bad_poll' in request.GET: @@ -26,27 +28,35 @@ def index(request): return render_to_response('main.html', response_dct) def createOrEdit(request, admin_url): - + '''Creation or edition of a poll. + admin_url is given to identify a particular poll + admin_url is equal to 0 for a new poll + response_dct is given to the template with some particular keys: + - error is an error message + - new is set to true if it is a new poll + - admin_url is the url of the current page + ''' def genRandomURL(): + "Generation of a random url" chars = string.letters + string.digits url = '' - for i in range(6): + for i in xrange(6): url += random_choice(chars) url += str(int(time.time())) return url - response_dct = getBaseResponse(request) - response_dct['TYPES'] = Poll.TYPE - error = None - poll = None - if 'new' in request.POST: + def submitNewPoll(request, response_dct): + "A new poll is submited" + # verify if all the mandatory_fields are set mandatory_fields = (('author_name', "Author name"), ('poll_name', "Poll name"), ('poll_desc', "Poll description"), ('poll_type', "Poll type"), ) + error = "" for key, label in mandatory_fields: if key not in request.POST or not request.POST[key]: + # only the first error is reported if not error: error = "%s is a mandatory field" % label else: @@ -54,47 +64,47 @@ def createOrEdit(request, admin_url): if error: response_dct['new'] = True response_dct['error'] = error - response_dct['admin_url'] = \ - "/".join(request.path.split('/')[:-2]) + '/0/' - else: - author = PollUser(name=request.POST['author_name']) - author.save() - base_url = 'b' + genRandomURL() - admin_url = 'a' + genRandomURL() - poll = Poll(name=request.POST['poll_name'], + response_dct['admin_url'] += '/0/' + return response_dct, None + author = PollUser(name=request.POST['author_name']) + author.save() + base_url = 'b' + genRandomURL() + admin_url = 'a' + genRandomURL() + poll = Poll(name=request.POST['poll_name'], description=request.POST['poll_desc'], author=author, base_url=base_url, admin_url=admin_url, status = 'D', type=request.POST['poll_type']) - poll.save() - url = "/".join(request.path.split('/')[:-2]) \ - + '/%s/' % poll.admin_url - return HttpResponseRedirect(url) - elif admin_url == '0': - response_dct['new'] = True - response_dct['admin_url'] = \ - "/".join(request.path.split('/')[:-2]) + '/0/' - else: + poll.save() + url = response_dct['admin_url'] + '/%s/' % poll.admin_url + return response_dct, HttpResponseRedirect(url) + + def getExistingPoll(request, response_dct, admin_url): + "Get an existing poll" try: poll = Poll.objects.filter(admin_url=admin_url)[0] except IndexError: - url = "/".join(request.path.split('/')[:-2]) + '/0/' - return HttpResponseRedirect(url) - response_dct['choices'] = Choice.objects.filter(poll=poll).order_by('order') - response_dct['author_name'] = poll.author.name - response_dct['poll_name'] = poll.name - response_dct['poll_desc'] = poll.description - idx = [type[0] for type in poll.TYPE].index(poll.type) - response_dct['type_name'] = Poll.TYPE[idx][1] - response_dct['poll_status'] = poll.status - response_dct['admin_url'] = \ - "/".join(request.path.split('/')[:-2]) + '/%s/' % poll.admin_url + # if the poll don't exist redirect to the creation page + url = response_dct['admin_url'] + '/0/' + return response_dct, HttpResponseRedirect(url) + # base feed of the template + new_dct = {'author_name':poll.author.name, + 'poll_name':poll.name, + 'poll_desc':poll.description, + 'choices':Choice.objects.filter(poll=poll).order_by('order'), + 'poll_status':poll.status, + 'type_name':poll.getTypeLabel()} + response_dct.update(new_dct) + + # urls base_path = request.META['HTTP_HOST'] + \ "/".join(request.path.split('/')[:-3]) - response_dct['full_admin_url'] = base_path + "/edit/" \ - + admin_url + "/" response_dct['base_url'] = poll.base_url response_dct['full_base_url'] = base_path + "/poll/" \ + poll.base_url + "/" - response_dct['choiceform'] = "<input type='text' name='new_choice'/>" + response_dct['admin_url'] += '/%s/' % poll.admin_url + response_dct['full_admin_url'] = base_path + "/edit/" \ + + admin_url + "/" + + # if a new choice is submitted if 'new_choice' in request.POST and request.POST['new_choice']: try: order = Choice.objects.order_by('-order')[0].order @@ -104,110 +114,194 @@ admin_url=admin_url, status = 'D', type=request.POST['poll_type']) choice = Choice(poll=poll, name=request.POST['new_choice'], order=order) choice.save() + # check if a choice has been choosen for deletion for key in request.POST: if key.startswith('delete_') and request.POST[key]: choice = Choice.objects.get(id=int(key[len('delete_'):])) Vote.objects.filter(choice=choice).delete() choice.delete() + return response_dct, None + + response_dct = getBaseResponse(request) + response_dct['TYPES'] = Poll.TYPE + response_dct['admin_url'] = \ + "/".join(request.path.split('/')[:-2]) + redirection = None + if 'new' in request.POST: + # new poll is submited + response_dct, redirection = submitNewPoll(request, response_dct) + elif admin_url == '0': + # new empty poll + response_dct['new'] = True + response_dct['admin_url'] += '/0/' + else: + # existing poll + response_dct, redirection = getExistingPoll(request, + response_dct, admin_url) + if redirection: + return redirection return render_to_response('createOrEdit.html', response_dct) def poll(request, poll_url): + "Display a poll" + + def modifyVote(request, choices): + "Modify user's votes" + try: + author = PollUser.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']: + for choice in choices: + v = Vote.objects.filter(voter=author, choice=choice) + v.delete() + author.delete() + return + # update the name + author.name = request.POST['author_name'] + author.save() + selected_choices = [] + # set the selected choices + for key in request.POST: + 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: + vote.vote = 1 + vote.save() + selected_choices.append(vote.choice) + except (ValueError, IndexError): + # the vote don't exist with this choice + v = Vote(voter=author, choice=choice, value=1) + v.save() + 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 + v = Vote(voter=author, choice=choice, value=1) + v.save() + selected_choices.append(choice) + except (ValueError, IndexError): + # bad choice id : the choice has probably been deleted + pass + # update non selected choices + for choice in choices: + if choice not in selected_choices: + try: + v = Vote.objects.filter(voter=author, choice=choice)[0] + v.vote = 0 + except IndexError: + # the vote don't exist with this choice : probably + # a new choice + v = Vote(voter=author, choice=choice, value=0) + v.save() + + def newVote(request, choices): + "Create new votes" + if not request.POST['author_name']: + return + author = PollUser(name=request.POST['author_name']) + author.save() + selected_choices = [] + + # set the selected choices + for key in request.POST: + 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 + v = Vote(voter=author, 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=author, choice=choice, value=0) + v.save() + response_dct = getBaseResponse(request) - error = None try: poll = Poll.objects.filter(base_url=poll_url)[0] except IndexError: poll = None choices = Choice.objects.filter(poll=poll).order_by('order') + # 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" + url += "/?bad_poll=1" return HttpResponseRedirect(url) - response_dct['base_url'] = \ - "/".join(request.path.split('/')[:-2]) + '/%s/' % poll.base_url - - response_dct['choices'] = choices + + # a vote is submitted if 'author_name' in request.POST: if 'voter' in request.POST: - try: - author = PollUser.objects.filter(id=int(request.POST['voter']))[0] - except (ValueError, IndexError): - author = None - if author: - author.name = request.POST['author_name'] - author.save() - selected_choices = [] - for key in request.POST: - 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: - raise ValueError - vote.vote = 1 - vote.save() - except (ValueError, IndexError): - url = "/".join(request.path.split('/')[:-3]) - url += "?bad_poll=1" - return HttpResponseRedirect(url) - selected_choices.append(vote.choice) - for choice in choices: - if choice not in selected_choices: - try: - v = Vote.objects.filter(voter=author, choice=choice)[0] - v.vote = 0 - except IndexError: - v = Vote(voter=author, choice=choice, vote=0) - v.save() - + # modification of an old vote + modifyVote(request, choices) else: - author = PollUser(name=request.POST['author_name']) - author.save() - selected_choices = [] - for key in request.POST: - 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 - except (ValueError, IndexError): - url = "/".join(request.path.split('/')[:-3]) - url += "?bad_poll=1" - return HttpResponseRedirect(url) - v = Vote(voter=author, choice=choice, vote=1) - selected_choices.append(choice) - v.save() - for choice in choices: - if choice not in selected_choices: - v = Vote(voter=author, choice=choice, vote=0) - v.save() - votes = [] + newVote(request, choices) + + # 'voter' is in request.GET when the edit button is pushed + if 'voter' in request.GET: + try: + response_dct['current_voter_id'] = int(request.GET['voter']) + except ValueError: + pass + + response_dct.update({'choices':choices, + 'poll_type_name':poll.getTypeLabel(), + 'poll_name':poll.name, + 'poll_desc':poll.description}) + response_dct['base_url'] = "/".join(request.path.split('/')[:-2]) \ + + '/%s/' % poll.base_url + + # get voters and sum for each choice for this poll + + votes = [] # all votes for this poll votes = Vote.objects.extra(where=['choice_id IN (%s)' \ % ",".join([str(choice.id) for choice in choices])]) + voters = [] choices_sum = [0 for choice in choices] choices_ids = [choice.id for choice in choices] for vote in votes: if vote.voter not in voters: + # initialize a votes list for the current voter vote.voter.votes = [None for choice in choices] voters.append(vote.voter) voter = vote.voter else: + # get the appropriate voter voter = voters[voters.index(vote.voter)] idx = choices_ids.index(vote.choice.id) + # associate vote in the votes list of the voter voter.votes[idx] = vote - choices_sum[idx] += vote.vote - response_dct['voters'] = voters - if 'voter' in request.GET: - try: - response_dct['current_voter_id'] = int(request.GET['voter']) - except ValueError: - pass - response_dct['voter'] = voters - response_dct['choices_sum'] = [str(sum) for sum in choices_sum] - response_dct['poll_type_name'] = poll.getTypeLabel() - response_dct['poll_name'] = poll.name - response_dct['poll_desc'] = poll.description + choices_sum[idx] += vote.value + # for undefined vote get the choice id + # on the template the distinction between the choice and the voter + # is made by the type of the "vote" + for voter in voters: + for vote in voter.votes: + if not vote: + idx = voter.votes.index(vote) + voter.votes[idx] = choices[idx].id + response_dct.update({'voters':voters, + 'voter':voters, + 'choices_sum':[str(sum) for sum in choices_sum] + }) return render_to_response('vote.html', response_dct) |