Skip to content
Snippets Groups Projects
Commit f8af2a0f authored by Ben Adida's avatar Ben Adida
Browse files

improved the CSV upload process to confirm what an upload looks like

parent 9547f791
No related branches found
No related tags found
No related merge requests found
......@@ -68,6 +68,7 @@ urlpatterns = patterns('',
# managing voters
(r'^/voters/$', voter_list),
(r'^/voters/upload$', voters_upload),
(r'^/voters/upload-cancel$', voters_upload_cancel),
(r'^/voters/list$', voters_list_pretty),
(r'^/voters/email$', voters_email),
(r'^/voters/(?P<voter_uuid>[^/]+)$', one_voter),
......
......@@ -448,6 +448,24 @@ class VoterFile(models.Model):
processing_finished_at = models.DateTimeField(auto_now_add=False, null=True)
num_voters = models.IntegerField(null=True)
def itervoters(self):
reader = unicode_csv_reader(open(self.voter_file.path, "rU"))
for voter_fields in reader:
# bad line
if len(voter_fields) < 1:
continue
return_dict = {'voter_id': voter_fields[0]}
if len(voter_fields) > 1:
return_dict['email'] = voter_fields[1]
if len(voter_fields) > 2:
return_dict['name'] = voter_fields[2]
yield return_dict
def process(self):
self.processing_started_at = datetime.datetime.utcnow()
self.save()
......
{% extends TEMPLATE_BASE %}
{% block content %}
<h2 class="title">{{election.name}} &mdash; Bulk Upload Voters &mdash; Confirm<span style="font-size:0.7em;">[<a href="{% url helios.views.one_election_view election.uuid %}">back to election</a>]</span></h2>
<p>
You have uploaded a file of voters. The first few rows of this file are:
</p>
<table>
<tr><th>Voter Login</th><th>Email Address</th><th>Name</th></tr>
{% for v in voters %}
<tr><td>{{v.voter_id}}</td><td>{{v.email}}</td><td>{{v.name}}</td></tr>
{% endfor %}
</table>
<p></p>
<form method="post" action="" id="upload_form">
Does this look right to you?
<input type="hidden" name="confirm_p" value="1" />
<input type="submit" value="Yes, let's go" />
</form>
<a href="{% url helios.views.voters_upload_cancel election.uuid %}">no, let me upload a different file</a>
{% endblock %}
......@@ -941,14 +941,36 @@ def voters_upload(request, election):
return render_template(request, 'voters_upload', {'election': election})
if request.method == "POST":
# we store the file away for future processing
voters_file = request.FILES['voters_file']
voter_file_obj = election.add_voters_file(voters_file)
if bool(request.POST.get('confirm_p', 0)):
# launch the background task to parse that file
tasks.voter_file_process.delay(voter_file_id = request.session['voter_file_id'])
del request.session['voter_file_id']
# launch the background task to parse that file
tasks.voter_file_process.delay(voter_file_id = voter_file_obj.id)
return HttpResponseRedirect(reverse(one_election_view, args=[election.uuid]))
else:
# we need to confirm
voters_file = request.FILES['voters_file']
voter_file_obj = election.add_voters_file(voters_file)
return HttpResponseRedirect(reverse(one_election_view, args=[election.uuid]))
request.session['voter_file_id'] = voter_file_obj.id
# import the first few lines to check
voters = [v for v in voter_file_obj.itervoters()][:5]
return render_template(request, 'voters_upload_confirm', {'election': election, 'voters': voters})
@election_admin()
def voters_upload_cancel(request, election):
"""
cancel upload of CSV file
"""
voter_file_id = request.session.get('voter_file_id', None)
if voter_file_id:
vf = VoterFile.objects.get(id = voter_file_id)
vf.delete()
del request.session['voter_file_id']
return HttpResponseRedirect(reverse(one_election_view, args=[election.uuid]))
@election_admin(frozen=True)
def voters_email(request, election):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment