diff --git a/helios/migrations/0004_auto_20170528_2025.py b/helios/migrations/0004_auto_20170528_2025.py
new file mode 100644
index 0000000000000000000000000000000000000000..d49bb63753f4438ab79c0ce4101f7e56f7bcf8be
--- /dev/null
+++ b/helios/migrations/0004_auto_20170528_2025.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('helios', '0003_auto_20160507_1948'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='election',
+            name='help_email',
+            field=models.EmailField(max_length=254, null=True),
+        ),
+        migrations.AlterField(
+            model_name='trustee',
+            name='email',
+            field=models.EmailField(max_length=254),
+        ),
+    ]
diff --git a/helios/models.py b/helios/models.py
index 86a31a5741e722b2b733923cff8c7105fa1bdcfa..96b6654184726d49157df5f8d651ad28cbe99d95 100644
--- a/helios/models.py
+++ b/helios/models.py
@@ -817,9 +817,9 @@ class Voter(HeliosModel):
   def __init__(self, *args, **kwargs):
     super(Voter, self).__init__(*args, **kwargs)
 
+  def get_user(self):
     # stub the user so code is not full of IF statements
-    if not self.user:
-      self.user = User(user_type='password', user_id=self.voter_email, name=self.voter_name)
+    return self.user or User(user_type='password', user_id=self.voter_email, name=self.voter_name)
 
   @classmethod
   @transaction.atomic
@@ -920,11 +920,11 @@ class Voter(HeliosModel):
 
   @property
   def name(self):
-    return self.user.name
+    return self.get_user().name
 
   @property
   def voter_id(self):
-    return self.user.user_id
+    return self.get_user().user_id
 
   @property
   def voter_id_hash(self):
@@ -945,14 +945,17 @@ class Voter(HeliosModel):
 
   @property
   def voter_type(self):
-    return self.user.user_type
+    return self.get_user().user_type
 
   @property
   def display_html_big(self):
-    return self.user.display_html_big
+    return self.get_user().display_html_big
       
   def send_message(self, subject, body):
-    self.user.send_message(subject, body)
+    self.get_user().send_message(subject, body)
+    
+  def can_update_status(self):
+    return self.get_user().can_update_status()
 
   def generate_password(self, length=10):
     if self.voter_password:
diff --git a/helios/tasks.py b/helios/tasks.py
index 7b30fbb48eb44f544609703376b170ca7b0129c7..5f7bba8730120e732a48f7467314e05dcfd7b639 100644
--- a/helios/tasks.py
+++ b/helios/tasks.py
@@ -22,7 +22,7 @@ def cast_vote_verify_and_store(cast_vote_id, status_update_message=None, **kwarg
 
     voter = cast_vote.voter
     election = voter.election
-    user = voter.user
+    user = voter.get_user()
 
     if result:
         # send the signal
@@ -71,7 +71,7 @@ def single_voter_email(voter_uuid, subject_template, body_template, extra_vars={
     subject = render_template_raw(None, subject_template, the_vars)
     body = render_template_raw(None, body_template, the_vars)
 
-    voter.user.send_message(subject, body)
+    voter.send_message(subject, body)
 
 @task()
 def single_voter_notify(voter_uuid, notification_template, extra_vars={}):
@@ -82,7 +82,7 @@ def single_voter_notify(voter_uuid, notification_template, extra_vars={}):
 
     notification = render_template_raw(None, notification_template, the_vars)
 
-    voter.user.send_notification(notification)
+    voter.send_notification(notification)
 
 @task()
 def election_compute_tally(election_id):
diff --git a/helios/templates/combine_decryptions.html b/helios/templates/combine_decryptions.html
index c14c762f5ae1b353ecf0d9436a6be55ed85240d7..3530867df835c5fbeb0d9d591b50d0842be7eb95 100644
--- a/helios/templates/combine_decryptions.html
+++ b/helios/templates/combine_decryptions.html
@@ -10,7 +10,7 @@
 
   <form method="POST" action="">
     <input type="hidden" name="csrf_token" value="{{csrf_token}}" />
-    <input type="submit" value="compute the tally!" />
+    <input type="submit" class="button" value="compute the tally!" />
   </form>
 
 {% endblock %}
diff --git a/helios/templates/election_compute_tally.html b/helios/templates/election_compute_tally.html
index c3c1cbd9a5291f26b1b0a15c33e3c5b108f9213a..fd98440e3466bdd0d5b1cbfbf8dcdaa263514289 100644
--- a/helios/templates/election_compute_tally.html
+++ b/helios/templates/election_compute_tally.html
@@ -18,7 +18,7 @@
 <form method="post" action="" onsubmit="alert('ok, tally has begun')" class="pretty">
 <input type="hidden" name="csrf_token" value="{{csrf_token}}" />
     
-<input class="pretty" type="submit" value="compute encrypted tally!" />
+<input class="button" type="submit" value="compute encrypted tally!" />
 <button onclick="document.location='./view'; return false;">never mind</button>
 </form>
 {% else %}
diff --git a/helios/templates/release_result.html b/helios/templates/release_result.html
index 9675b02a1b3e11f3b79a1197b517a8d56d569ba5..cac6c64a7a6e62d07691ecbf877d09780607c495 100644
--- a/helios/templates/release_result.html
+++ b/helios/templates/release_result.html
@@ -13,7 +13,7 @@
     <p>
     <input type="checkbox" name="send_email" value="send_email" checked="checked"/> Send email to voters reporting release of result.
     </p>
-    <input type="submit" value="release result!" />
+    <input type="submit" class="button" value="release result!" />
   </form>
 
 {% endblock %}
diff --git a/helios/tests.py b/helios/tests.py
index 13557aea45965542d428456371ef5225fd1b4c94..542df03339183e24e4a4c156b5a6abd53bc93054 100644
--- a/helios/tests.py
+++ b/helios/tests.py
@@ -250,7 +250,7 @@ class VoterModelTests(TestCase):
         self.assertRaises(Exception, lambda: v.generate_password())
         
         # check that you can get at the voter user structure
-        self.assertEquals(v.user.user_id, v.voter_email)
+        self.assertEquals(v.get_user().user_id, v.voter_email)
 
 
 class CastVoteModelTests(TestCase):
@@ -424,8 +424,8 @@ class ElectionBlackboxTests(WebTest):
 
         # set up the app, too
         # this does not appear to work, boohoo
-        session = self.app.session
-        session['user'] = {'type': self.user.user_type, 'user_id': self.user.user_id}
+        #session = self.app.session
+        #session['user'] = {'type': self.user.user_type, 'user_id': self.user.user_id}
 
     def clear_login(self):
         session = self.client.session
@@ -642,7 +642,7 @@ class ElectionBlackboxTests(WebTest):
         self.assertRedirects(response, "%s/helios/elections/%s/cast_confirm" % (settings.SECURE_URL_HOST, election_id))
 
         cast_confirm_page = response.follow()
-
+        
         if need_login:
             if check_user_logged_in:
                 self.assertContains(cast_confirm_page, "You are logged in as")
@@ -653,12 +653,7 @@ class ElectionBlackboxTests(WebTest):
             login_form['voter_id'] = username
             login_form['password'] = password
 
-            # we skip that intermediary page now
-            # cast_confirm_page = login_form.submit()
             response = login_form.submit()
-
-            # self.assertRedirects(cast_confirm_page, "/helios/elections/%s/cast_confirm" % election_id)
-            # cast_confirm_page = cast_confirm_page.follow()
         else:
             # here we should be at the cast-confirm page and logged in
             self.assertContains(cast_confirm_page, "CAST this ballot")
@@ -751,7 +746,7 @@ class ElectionBlackboxTests(WebTest):
         ## for now the above does not work, it's a testing problem
         ## where the cookie isn't properly set. We'll have to figure this out.
         ## FIXME FIXME FIXME 
-        # self._cast_ballot(election_id, username, password, check_user_logged_in=True)
+        #self._cast_ballot(election_id, username, password, check_user_logged_in=True)
         self._cast_ballot(election_id, username, password, check_user_logged_in=False)
         self.clear_login()
 
diff --git a/helios/views.py b/helios/views.py
index d51191baa2bbaa2a38efedeb582113301a1ede3a..2959463db664c989371b021338ace8a48abca19f 100644
--- a/helios/views.py
+++ b/helios/views.py
@@ -622,7 +622,7 @@ def one_election_cast_confirm(request, election):
     return render_template(request, 'election_not_started', {'election': election})
 
   voter = get_voter(request, user, election)
-
+  
   # auto-register this person if the election is openreg
   if user and not voter and election.openreg:
     voter = _register_voter(election, user)
@@ -677,7 +677,7 @@ def one_election_cast_confirm(request, election):
     bad_voter_login = (request.GET.get('bad_voter_login', "0") == "1")
 
     # status update this vote
-    if voter and voter.user.can_update_status():
+    if voter and voter.can_update_status():
       status_update_label = voter.user.update_status_template() % "your smart ballot tracker"
       status_update_message = "I voted in %s - my smart tracker is %s.. #heliosvoting" % (get_election_url(election),cast_vote.vote_hash[:10])
     else:
@@ -761,7 +761,8 @@ def one_election_cast_done(request, election):
 
     # only log out if the setting says so *and* we're dealing
     # with a site-wide voter. Definitely remove current_voter
-    if voter.user == user:
+    # checking that voter.user != None is needed because voter.user may now be None if voter is password only
+    if voter.user == user and voter.user != None:
       logout = settings.LOGOUT_ON_CONFIRMATION
     else:
       logout = False
diff --git a/requirements.txt b/requirements.txt
index 6bf946f25f30a7e47725360b836114a225cd39ae..4f2b599376306783f63c175dc0af6cbdbe1fd6c9 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-Django==1.7.10
+Django==1.8.18
 anyjson==0.3.3
 celery==3.1.18
 django-celery==3.1.16