Exemple #1
0
def add_edit(request, election, poll=None):
    if not poll and not election.feature_can_add_poll:
        raise PermissionDenied
    if poll and not poll.feature_can_edit:
        raise PermissionDenied
    if election.linked_polls and 'batch_file' in request.FILES:
        return _add_batch(request, election)
    if poll:
        oldname = poll.name
    if request.method == "POST":
        form = PollForm(request.POST, instance=poll, election=election)
        if form.is_valid():
            new_poll = form.save()
            if form.has_changed():
                new_poll.logger.info("Poll updated %r" % form.changed_data)
            message = _("Poll updated successfully")
            messages.success(request, message)
            newname = new_poll.name
            # log poll edit/creation
            if poll:
                if oldname != newname:
                    poll.logger.info("Renamed from %s to %s", oldname, newname)
            else:
                new_poll.logger.info("Poll created")
            url = election_reverse(election, 'polls_list')
            return redirect(url)
    if request.method == "GET":
        form = PollForm(instance=poll, election=election)
    context = {'election': election, 'poll': poll, 'form': form}
    set_menu('polls', context)
    if poll:
        set_menu('edit_poll', context)
    tpl = "election_poll_add_or_edit"
    return render_template(request, tpl, context)
Exemple #2
0
def audited_ballots(request, election, poll):
    vote_hash = request.GET.get('vote_hash', None)
    if vote_hash:
        b = get_object_or_404(AuditedBallot, poll=poll, vote_hash=vote_hash)
        b = AuditedBallot.objects.get(poll=poll,
                                      vote_hash=request.GET['vote_hash'])
        return HttpResponse(b.raw_vote, content_type="text/plain")

    audited_ballots = AuditedBallot.objects.filter(is_request=False, poll=poll)

    voter = None
    if request.zeususer.is_voter:
        voter = request.voter

    voter_audited_ballots = []
    if voter:
        voter_audited_ballots = AuditedBallot.objects.filter(poll=poll,
                                                             is_request=False,
                                                             voter=voter)
    context = {
        'election': election,
        'audited_ballots': audited_ballots,
        'voter_audited_ballots': voter_audited_ballots,
        'poll': poll,
        'per_page': 50
    }
    set_menu('audited_ballots', context)
    return render_template(request, 'election_poll_audited_ballots', context)
Exemple #3
0
def index(request, election, poll=None):
    user = request.zeususer

    if poll:
        election_url = poll.get_absolute_url()
    else:
        election_url = election.get_absolute_url()

    booth_url = None
    linked_booth_urls = []
    if poll:
        booth_url = poll.get_booth_url(request)
        if poll.has_linked_polls and user.is_voter:
            for p in poll.linked_polls:
                if p == poll:
                    continue
                try:
                    voter = \
                        p.voters.get(voter_login_id=user._user.voter_login_id)
                except Exception as e:
                    continue
                burl = reverse('election_poll_voter_booth_linked_login',
                               args=(
                                   election.uuid,
                                   poll.uuid,
                                   voter.uuid,
                               ))
                burl = burl + "?link-to=%s" % p.uuid
                linked_booth_urls.append((p.name, burl, voter.cast_at))

    voter = None
    votes = None
    if user.is_voter:
        # cast any votes?
        voter = request.voter
        votes = voter.get_cast_votes()
        if election.frozen_at:
            voter.last_visit = datetime.datetime.now()
            voter.save()
        else:
            votes = None

    trustees = election.trustees.filter()

    context = {
        'election': election,
        'poll': poll,
        'trustees': trustees,
        'user': user,
        'votes': votes,
        'election_url': election_url,
        'booth_url': booth_url,
        'linked_booth_urls': linked_booth_urls
    }
    if poll:
        context['poll'] = poll

    set_menu('election', context)
    return render_template(request, 'election_view', context)
Exemple #4
0
    def questions_update_view(self, request, election, poll):
        from zeus.utils import poll_reverse
        from zeus.forms import PartyForm, DEFAULT_ANSWERS_COUNT, \
                MAX_QUESTIONS_LIMIT

        extra = 1
        if poll.questions_data:
            extra = 0

        questions_formset = formset_factory(PartyForm,
                                            extra=extra,
                                            can_delete=True,
                                            can_order=True)
        if request.method == 'POST':
            formset = questions_formset(request.POST)
            if formset.is_valid():
                questions_data = []
                for question in formset.cleaned_data:
                    if not question:
                        continue

                    # force sort of answers by extracting index from answer key.
                    # cast answer index to integer, otherwise answer_10 would
                    # be placed before answer_2
                    answer_index = lambda a: int(a[0].replace('answer_', ''))
                    isanswer = lambda a: a[0].startswith('answer_')
                    answer_values = list(
                        filter(isanswer, iter(question.items())))
                    sorted_answers = sorted(answer_values, key=answer_index)

                    answers = [x[1] for x in sorted_answers]
                    question['answers'] = answers
                    for k in list(question.keys()):
                        if k in ['DELETE', 'ORDER']:
                            del question[k]

                    questions_data.append(question)

                poll.questions_data = questions_data
                poll.update_answers()
                poll.logger.info("Poll ballot updated")
                poll.save()

                url = poll_reverse(poll, 'questions')
                return HttpResponseRedirect(url)
        else:
            formset = questions_formset(initial=poll.questions_data)

        context = {
            'default_answers_count': DEFAULT_ANSWERS_COUNT,
            'formset': formset,
            'max_questions_limit': MAX_QUESTIONS_LIMIT,
            'election': election,
            'poll': poll,
            'module': self
        }
        set_menu('questions', context)
        tpl = 'election_modules/parties/election_poll_questions_manage'
        return render_template(request, tpl, context)
Exemple #5
0
def home(request, election, trustee):
    context = {'election': election, 'trustee': trustee}
    if not trustee.public_key:
        url = election_reverse(election, 'trustee_keygen')
        return HttpResponseRedirect(url)

    set_menu('trustee', context)
    return render_template(request, 'election_trustee_home', context)
Exemple #6
0
def voters_list(request, election, poll):
    # for django pagination support
    page = int(request.GET.get('page', 1))
    limit = int(request.GET.get('limit', 10))
    q_param = request.GET.get('q', '')

    default_voters_per_page = getattr(settings, 'ELECTION_VOTERS_PER_PAGE',
                                      100)
    voters_per_page = request.GET.get('limit', default_voters_per_page)
    try:
        voters_per_page = int(voters_per_page)
    except:
        voters_per_page = default_voters_per_page
    order_by = request.GET.get('order', 'voter_login_id')
    order_type = request.GET.get('order_type', 'desc')

    module = election.get_module()
    table_headers = copy.copy(module.get_voters_list_headers(request))
    if order_by not in table_headers:
        order_by = 'voter_login_id'

    if not poll.voters.filter(voter_weight__gt=1).count():
        table_headers.pop('voter_weight')
    display_weight_col = 'voter_weight' in table_headers

    validate_hash = request.GET.get('vote_hash', "").strip()
    hash_invalid = None
    hash_valid = None

    if (order_type == 'asc') or (order_type is None):
        voters = Voter.objects.filter(poll=poll).annotate(
            cast_votes__id=Max('cast_votes__id')).order_by(order_by)
    else:
        order_by = '-%s' % order_by
        voters = Voter.objects.filter(poll=poll).annotate(
            cast_votes__id=Max('cast_votes__id')).order_by(order_by)

    voters = module.filter_voters(voters, q_param, request)
    voters_count = Voter.objects.filter(poll=poll).count()
    voted_count = poll.voters_cast_count()
    nr_voters_excluded = voters.excluded().count()
    context = {
        'election': election,
        'poll': poll,
        'page': page,
        'voters': voters,
        'voters_count': voters_count,
        'voted_count': voted_count,
        'q': q_param,
        'voters_list_count': voters.count(),
        'voters_per_page': voters_per_page,
        'display_weight_col': display_weight_col,
        'voter_table_headers': table_headers,
        'voter_table_headers_iter': iter(table_headers.items()),
        'nr_voters_excluded': nr_voters_excluded,
    }
    set_menu('voters', context)
    return render_template(request, 'election_poll_voters_list', context)
Exemple #7
0
    def questions_update_view(self, request, election, poll):
        from zeus.utils import poll_reverse
        from zeus.forms import PartyForm, DEFAULT_ANSWERS_COUNT, \
                MAX_QUESTIONS_LIMIT

        extra = 1
        if poll.questions_data:
            extra = 0

        questions_formset = formset_factory(PartyForm, extra=extra,
                                            can_delete=True, can_order=True)
        if request.method == 'POST':
            formset = questions_formset(request.POST)
            if formset.is_valid():
                questions_data = []
                for question in formset.cleaned_data:
                    if not question:
                        continue

                    # force sort of answers by extracting index from answer key.
                    # cast answer index to integer, otherwise answer_10 would
                    # be placed before answer_2
                    answer_index = lambda a: int(a[0].replace('answer_', ''))
                    isanswer = lambda a: a[0].startswith('answer_')
                    answer_values = filter(isanswer, question.iteritems())
                    sorted_answers = sorted(answer_values, key=answer_index)

                    answers = [x[1] for x in sorted_answers]
                    question['answers'] = answers
                    for k in question.keys():
                        if k in ['DELETE', 'ORDER']:
                            del question[k]

                    questions_data.append(question)

                poll.questions_data = questions_data
                poll.update_answers()
                poll.logger.info("Poll ballot updated")
                poll.save()

                url = poll_reverse(poll, 'questions')
                return HttpResponseRedirect(url)
        else:
            formset = questions_formset(initial=poll.questions_data)

        context = {
            'default_answers_count': DEFAULT_ANSWERS_COUNT,
            'formset': formset,
            'max_questions_limit': MAX_QUESTIONS_LIMIT,
            'election': election,
            'poll': poll,
            'module': self
        }
        set_menu('questions', context)
        tpl = 'election_modules/parties/election_poll_questions_manage'
        return render_template(request, tpl, context)
Exemple #8
0
def results(request, election, poll):
    if not request.zeususer.is_admin and not poll.feature_public_results:
        raise PermissionDenied('41')

    if not poll.get_module().display_poll_results:
        url = election_reverse(election, 'index')
        return HttpResponseRedirect(url)

    context = {'poll': poll, 'election': election}
    set_menu('results', context)
    return render_template(request, 'election_poll_results', context)
Exemple #9
0
def add_or_update(request, election=None):
    user = request.admin
    institution = user.institution

    if request.method == "GET":
        election_form = ElectionForm(user,
                                     institution,
                                     instance=election,
                                     lang=request.LANGUAGE_CODE)
    else:
        election_form = ElectionForm(user,
                                     institution,
                                     request.POST,
                                     instance=election)

    if election_form.is_valid():
        creating = election is None
        with transaction.atomic():
            election = election_form.save()
            if not election.admins.filter(pk=user.pk).count():
                election.admins.add(user)
            if election_form.creating:
                election.logger.info("Election created")
                msg = "New election created"
                subject = "New Zeus election"
                election.notify_admins(msg=msg, subject=subject)
            if not election.has_helios_trustee():
                election.generate_trustee()
            if election.polls.count() == 0:
                url = election_reverse(election, 'polls_add')
            else:
                url = election_reverse(election, 'index')
            if election.voting_extended_until:
                subject = "Voting extension"
                msg = "Voting end date extended"
                election.notify_admins(msg=msg, subject=subject)

            election.zeus.compute_election_public()
            election.logger.info("Public key updated")
            hook_url = None
            if creating:
                hook_url = election.get_module().run_hook('post_create')
            else:
                hook_url = election.get_module().run_hook('post_update')
            return HttpResponseRedirect(hook_url or url)

    context = {'election_form': election_form, 'election': election}
    set_menu('election_edit', context)
    tpl = "election_new"
    if election and election.pk:
        tpl = "election_edit"
    return render_template(request, tpl, context)
Exemple #10
0
def questions(request, election, poll):
    module = poll.get_module()
    if request.zeususer.is_admin:
        if not module.questions_set() and poll.feature_can_manage_questions:
            url = poll_reverse(poll, 'questions_manage')
            return HttpResponseRedirect(url)

    preview_booth_url = poll.get_booth_url(request, preview=True)
    context = {
        'election': election,
        'poll': poll,
        'questions': questions,
        'module': poll.get_module(),
        'preview_booth_url': preview_booth_url
    }
    set_menu('questions', context)
    tpl = getattr(module, 'questions_list_template', 'election_poll_questions')
    return render_template(request, tpl, context)
Exemple #11
0
    def questions_update_view(self, request, election, poll):
        from zeus.utils import poll_reverse
        from zeus.forms import DEFAULT_ANSWERS_COUNT, \
                MAX_QUESTIONS_LIMIT

        extra = 1
        if poll.questions_data:
            extra = 0

        questions_formset = self.questions_formset(extra)
        if request.method == 'POST':
            formset = questions_formset(request.POST,
                                        request.FILES,
                                        initial=poll.questions_data)
            should_submit = not request.FILES and formset.is_valid()
            if should_submit:
                cleaned_data = formset.cleaned_data
                questions_data = self.extract_question_data(cleaned_data)

                poll.questions_data = questions_data
                poll.update_answers()
                poll.logger.info("Poll ballot updated")
                self.update_poll_params(poll, formset.cleaned_data)
                poll.save()

                url = poll_reverse(poll, 'questions')
                return HttpResponseRedirect(url)
        else:
            formset = questions_formset(initial=poll.questions_data)

        context = {
            'default_answers_count': DEFAULT_ANSWERS_COUNT,
            'formset': formset,
            'max_questions_limit': self.max_questions_limit
            or MAX_QUESTIONS_LIMIT,
            'election': election,
            'poll': poll,
            'module': self
        }
        set_menu('questions', context)
        tpl = f'election_modules/{self.module_id}/election_poll_questions_manage'
        return render_template(request, tpl, context)
Exemple #12
0
def trustees_list(request, election):
    trustees = election.trustees.filter(election=election,
                                        secret_key__isnull=True).order_by('pk')

    # TODO: can we move this in a context processor
    # or middleware ???
    voter = None
    poll = None
    if getattr(request, 'voter', None):
        voter = request.voter
        poll = voter.poll

    context = {
        'election': election,
        'poll': poll,
        'voter': voter,
        'trustees': trustees
    }
    set_menu('trustees', context)
    return render_template(request, 'election_trustees_list', context)
Exemple #13
0
    def questions_update_view(self, request, election, poll):
        from zeus.utils import poll_reverse
        from zeus.forms import QuestionForm, DEFAULT_ANSWERS_COUNT, \
                MAX_QUESTIONS_LIMIT

        extra = 1
        if poll.questions_data:
            extra = 0

        questions_formset = self.questions_formset(extra)
        if request.method == 'POST':
            formset = questions_formset(request.POST)
            if formset.is_valid():
                cleaned_data = formset.cleaned_data
                questions_data = self.extract_question_data(cleaned_data)

                poll.questions_data = questions_data
                poll.update_answers()
                poll.logger.info("Poll ballot updated")
                poll.save()

                url = poll_reverse(poll, 'questions')
                return HttpResponseRedirect(url)
        else:
            formset = questions_formset(initial=poll.questions_data)

        context = {
            'default_answers_count': DEFAULT_ANSWERS_COUNT,
            'formset': formset,
            'max_questions_limit': MAX_QUESTIONS_LIMIT,
            'election': election,
            'poll': poll,
            'module': self
        }
        set_menu('questions', context)
        tpl = 'election_modules/simple/election_poll_questions_manage'
        return render_template(request, tpl, context)
Exemple #14
0
def test_set_menu():
    menu = 'menu'
    ctx = {}
    utils.set_menu(menu, ctx)
    assert ctx['menu_active'] == menu
Exemple #15
0
def voters_email(request, election, poll=None, voter_uuid=None):
    user = request.admin

    TEMPLATES = [
        ('vote', _('Time to Vote')),
        ('info', _('Additional Info')),
    ]

    default_template = 'vote'

    if not election.any_poll_feature_can_send_voter_mail:
        raise PermissionDenied('34')

    if not election.any_poll_feature_can_send_voter_booth_invitation:
        TEMPLATES.pop(0)
        default_template = 'info'

    polls = [poll]
    if not poll:
        polls = election.polls_by_link_id

    voter = None
    if voter_uuid:
        try:
            if poll:
                voter = get_object_or_404(Voter, uuid=voter_uuid, poll=poll)
            else:
                voter = get_object_or_404(Voter,
                                          uuid=voter_uuid,
                                          election=election)
        except Voter.DoesNotExist:
            raise PermissionDenied('35')
        if not voter:
            url = election_reverse(election, 'index')
            return HttpResponseRedirect(url)

        if voter.excluded_at:
            TEMPLATES.pop(0)
            default_template = 'info'

    if election.voting_extended_until and not election.voting_ended_at:
        if not voter or (voter and not voter.excluded_at):
            TEMPLATES.append(('extension', _('Voting end date extended')))

    if request.method == 'POST':
        template = request.POST.get('template', default_template)
    else:
        template = request.GET.get('template', default_template)

    if template not in [t[0] for t in TEMPLATES]:
        raise Exception("bad template")

    election_url = election.get_absolute_url()

    default_subject = render_to_string('email/%s_subject.txt' % template,
                                       {'custom_subject': "<SUBJECT>"})

    tpl_context = {
        'election': election,
        'election_url': election_url,
        'custom_subject': default_subject,
        'custom_message': '<BODY>',
        'custom_message_sms': '<SMS_BODY>',
        'SECURE_URL_HOST': settings.SECURE_URL_HOST,
        'voter': {
            'vote_hash': '<SMART_TRACKER>',
            'name': '<VOTER_NAME>',
            'voter_name': '<VOTER_NAME>',
            'voter_surname': '<VOTER_SURNAME>',
            'voter_login_id': '<VOTER_LOGIN_ID>',
            'voter_password': '******',
            'login_code': '<VOTER_LOGIN_CODE>',
            'audit_passwords': '1',
            'get_audit_passwords': ['pass1', 'pass2', '...'],
            'get_quick_login_url': '<VOTER_LOGIN_URL>',
            'poll': poll,
            'election': election
        }
    }

    default_body = render_to_string('email/%s_body.txt' % template,
                                    tpl_context)

    default_sms_body = render_to_string('sms/%s_body.txt' % template,
                                        tpl_context)

    q_param = request.GET.get('q', None)

    filtered_voters = election.voters.filter()
    if poll:
        filtered_voters = poll.voters.filter()

    if not q_param:
        filtered_voters = filtered_voters.none()
    else:
        filtered_voters = election.get_module().filter_voters(
            filtered_voters, q_param, request)

        if not filtered_voters.count():
            message = _("No voters were found.")
            messages.error(request, message)
            url = election_reverse(election, 'polls_list')
            return HttpResponseRedirect(url)

    if request.method == "GET":
        email_form = EmailVotersForm(election, template)
        email_form.fields['email_subject'].initial = dict(TEMPLATES)[template]
        if voter:
            email_form.fields['send_to'].widget = \
                email_form.fields['send_to'].hidden_widget()
    else:
        email_form = EmailVotersForm(election, template, request.POST)
        if email_form.is_valid():
            # the client knows to submit only once with a specific voter_id
            voter_constraints_include = None
            voter_constraints_exclude = None
            update_booth_invitation_date = False
            if template == 'vote':
                update_booth_invitation_date = True

            if voter:
                voter_constraints_include = {'uuid': voter.uuid}

            # exclude those who have not voted
            if email_form.cleaned_data['send_to'] == 'voted':
                voter_constraints_exclude = {'vote_hash': None}

            # include only those who have not voted
            if email_form.cleaned_data['send_to'] == 'not-voted':
                voter_constraints_include = {'vote_hash': None}

            for _poll in polls:
                if not _poll.feature_can_send_voter_mail:
                    continue

                if template == 'vote' and not \
                        _poll.feature_can_send_voter_booth_invitation:
                    continue

                subject_template = 'email/%s_subject.txt' % template
                body_template = 'email/%s_body.txt' % template
                body_template_sms = 'sms/%s_body.txt' % template
                contact_method = email_form.cleaned_data['contact_method']

                extra_vars = {
                    'SECURE_URL_HOST': settings.SECURE_URL_HOST,
                    'custom_subject': email_form.cleaned_data['email_subject'],
                    'custom_message': email_form.cleaned_data['email_body'],
                    'custom_message_sms': email_form.cleaned_data['sms_body'],
                    'election_url': election_url,
                }
                task_kwargs = {
                    'contact_id': template,
                    'notify_once': email_form.cleaned_data.get('notify_once'),
                    'subject_template_email': subject_template,
                    'body_template_email': body_template,
                    'body_template_sms': body_template_sms,
                    'contact_methods': contact_method.split(":"),
                    'template_vars': extra_vars,
                    'voter_constraints_include': voter_constraints_include,
                    'voter_constraints_exclude': voter_constraints_exclude,
                    'update_date': True,
                    'update_booth_invitation_date':
                    update_booth_invitation_date,
                    'q_param': q_param,
                }
                log_obj = election
                if poll:
                    log_obj = poll
                if voter:
                    log_obj.logger.info(
                        "Notifying single voter %s, [template: %s, filter: %s]",
                        voter.voter_login_id, template, q_param)
                else:
                    log_obj.logger.info(
                        "Notifying voters, [template: %s, filter: %r]",
                        template, q_param)
                tasks.voters_email.delay(_poll.pk, **task_kwargs)

            filters = get_voters_filters_with_constraints(
                q_param, voter_constraints_include, voter_constraints_exclude)
            send_to = filtered_voters.filter(filters)
            if q_param and not send_to.filter(filters).count():
                msg = "No voters matched your filters. No emails were sent."
                messages.error(request, _(msg))
            else:
                messages.info(request, _("Email sending started"))

            url = election_reverse(election, 'polls_list')
            if poll:
                url = poll_reverse(poll, 'voters')
            if q_param:
                url += '?q=%s' % six.moves.urllib.parse.quote_plus(q_param)
            return HttpResponseRedirect(url)
        else:
            message = _("Something went wrong")
            messages.error(request, message)

    if election.sms_enabled and election.sms_data.left <= 0:
        messages.warning(request, _("No SMS deliveries left."))

    context = {
        'email_form': email_form,
        'election': election,
        'poll': poll,
        'voter_o': voter,
        'default_subject': default_subject,
        'default_body': default_body,
        'default_sms_body': default_sms_body,
        'sms_enabled': election.sms_enabled,
        'template': template,
        'filtered_voters': filtered_voters,
        'templates': TEMPLATES
    }
    set_menu('voters', context)
    if not poll:
        set_menu('polls', context)
    return render_template(request, "voters_email", context)
Exemple #16
0
def polls_list(request, election):
    polls = election.polls.filter()
    context = {'polls': polls, 'election': election}
    set_menu('polls', context)
    return render_template(request, "election_polls_list", context)
Exemple #17
0
def voters_upload(request, election, poll):
    common_context = {
        'election': election,
        'poll': poll,
        'encodings': ENCODINGS
    }

    set_menu('voters', common_context)
    if request.method == "POST":
        preferred_encoding = request.POST.get('encoding', None)
        if preferred_encoding not in dict(ENCODINGS):
            messages.error(request, _("Invalid encoding"))
            url = poll_reverse(poll, 'voters_upload')
            return HttpResponseRedirect(url)
        else:
            common_context['preferred_encoding'] = preferred_encoding

        if bool(request.POST.get('confirm_p', 0)):
            # launch the background task to parse that file
            voter_file_id = request.session.get('voter_file_id', None)
            process_linked = request.session.get('no_link', False) is False
            if not voter_file_id:
                messages.error(request, _("Invalid voter file id"))
                url = poll_reverse(poll, 'voters')
                return HttpResponseRedirect(url)
            try:
                voter_file = VoterFile.objects.get(pk=voter_file_id)
                try:
                    voter_file.process(process_linked,
                                       preferred_encoding=preferred_encoding)
                except (exceptions.VoterLimitReached,
                        exceptions.DuplicateVoterID, ValidationError) as e:
                    messages.error(request, e.message)
                    voter_file.delete()
                    url = poll_reverse(poll, 'voters')
                    return HttpResponseRedirect(url)

                poll.logger.info("Processing voters upload")
            except VoterFile.DoesNotExist:
                pass
            except KeyError:
                pass
            if 'no_link' in request.session:
                del request.session['no_link']
            if 'voter_file_id' in request.session:
                del request.session['voter_file_id']
            url = poll_reverse(poll, 'voters')
            return HttpResponseRedirect(url)
        else:
            if 'voter_file_id' in request.session:
                del request.session['voter_file_id']
            # we need to confirm
            voters = []
            error = None
            invalid_emails = []

            def _email_validate(eml, line):
                try:
                    validate_email(eml)
                except ValidationError:
                    invalid_emails.append((eml, line))
                return True

            if 'voters_file' in request.FILES:
                voters_file = request.FILES['voters_file']
                voter_file_obj = poll.add_voters_file(voters_file)

                # import the first few lines to check
                invalid_emails = []
                try:
                    voters = [
                        v for v in voter_file_obj.itervoters(
                            email_validator=_email_validate,
                            preferred_encoding=preferred_encoding)
                    ]
                except ValidationError as e:
                    if hasattr(e, 'messages') and e.messages:
                        error = "".join(e.messages)
                    else:
                        error = "error."
                except Exception as e:
                    logging.exception('error reading voter file')
                    voter_file_obj.delete()
                    error = str(e)
                    if 'voter_file_id' in request.session:
                        del request.session['voter_file_id']
                    messages.error(request, error)
                    url = poll_reverse(poll, 'voters_upload')
                    return HttpResponseRedirect(url)

                if len(invalid_emails):
                    error = _("Enter a valid email address. " "<br />")
                    for email, line in invalid_emails:
                        error += "<br />" + "line %d: %s " % (line,
                                                              escape(email))

                    error = mark_safe(error)
            else:
                error = _("No file uploaded")
            if not error:
                request.session['voter_file_id'] = voter_file_obj.id
            count = len(voters)
            context = common_context
            context.update({'voters': voters, 'count': count, 'error': error})
            return render_template(request,
                                   'election_poll_voters_upload_confirm',
                                   context)
    else:
        if 'voter_file_id' in request.session:
            del request.session['voter_file_id']
        no_link = bool(request.GET.get("no-link", False))
        request.session['no_link'] = no_link
        return render_template(request, 'election_poll_voters_upload',
                               common_context)
Exemple #18
0
    def questions_update_view(self, request, election, poll):
        from zeus.utils import poll_reverse
        from zeus.forms import StvForm, DEFAULT_ANSWERS_COUNT

        if not poll.questions_data:
            poll.questions_data = [{}]

        poll.questions_data[0]['departments_data'] = election.departments
        initial = poll.questions_data

        extra = 1
        if poll.questions_data:
            extra = 0

        questions_formset = formset_factory(StvForm,
                                            extra=extra,
                                            can_delete=True,
                                            can_order=True)

        if request.method == 'POST':
            formset = questions_formset(request.POST, initial=initial)

            if formset.is_valid():
                questions_data = []

                for question in formset.cleaned_data:
                    if not question:
                        continue
                    # force sort of answers by extracting index from answer key.
                    # cast answer index to integer, otherwise answer_10 would
                    # be placed before answer_2
                    answer_index = lambda a: int(a[0].replace('answer_', ''))
                    isanswer = lambda a: a[0].startswith('answer_')

                    answer_values = list(
                        filter(isanswer, iter(question.items())))
                    sorted_answers = sorted(answer_values, key=answer_index)

                    answers = [json.loads(x[1])[0] for x in sorted_answers]
                    departments = [json.loads(x[1])[1] for x in sorted_answers]

                    final_answers = []
                    for a, d in zip(answers, departments):
                        final_answers.append(a + ':' + d)
                    question['answers'] = final_answers
                    for k in list(question.keys()):
                        if k in ['DELETE', 'ORDER']:
                            del question[k]

                    questions_data.append(question)

                poll.questions_data = questions_data
                poll.update_answers()
                poll.logger.info("Poll ballot updated")
                poll.eligibles_count = int(
                    formset.cleaned_data[0]['eligibles'])
                poll.has_department_limit = formset.cleaned_data[0][
                    'has_department_limit']
                poll.department_limit = int(
                    formset.cleaned_data[0]['department_limit'])
                poll.save()

                url = poll_reverse(poll, 'questions')
                return HttpResponseRedirect(url)
        else:
            formset = questions_formset(initial=initial)

        context = {
            'default_answers_count': DEFAULT_ANSWERS_COUNT,
            'formset': formset,
            'max_questions_limit': 1,
            'election': election,
            'poll': poll,
            'module': self
        }
        set_menu('questions', context)

        tpl = 'election_modules/stv/election_poll_questions_manage'
        return render_template(request, tpl, context)