Skip to content

Instantly share code, notes, and snippets.

@jacoor
Created February 18, 2014 10:06
Show Gist options
  • Save jacoor/9067973 to your computer and use it in GitHub Desktop.
Save jacoor/9067973 to your computer and use it in GitHub Desktop.
basic django user account model + tests + admin
# -*- coding: utf-8 -*-
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import ugettext_lazy as _
from earnest.accounts.models import Account, AccessHistory
from earnest.accounts.forms import AdminPasswordChangeForm, AdminRegisterUserFullForm
class ReadonlyTabularInline(admin.TabularInline):
can_delete = False
extra = 0
editable_fields = []
def get_readonly_fields(self, request, obj=None):
fields = []
for field in self.model._meta.get_all_field_names():
if (not field == 'id'):
if (field not in self.editable_fields):
fields.append(field)
return fields
def has_add_permission(self, request):
return False
class AccessHistoryInline(ReadonlyTabularInline):
model = AccessHistory
editable_fields = []
class AccountAdmin(UserAdmin):
list_display = ('email',)
ordering = ('email',)
inlines = [
AccessHistoryInline,
]
readonly_fields = ('date_joined',)
change_password_form = AdminPasswordChangeForm
add_form = AdminRegisterUserFullForm
fieldsets = ()
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': AdminRegisterUserFullForm.Meta.fields,
}
),
)
#admin.site.disable_action('edit_permissions')
admin.site.register(Account, AccountAdmin)
# -*- coding: utf-8 -*-
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
class Emailbackend(ModelBackend):
def authenticate(self, email=None, password=None, *args, **kwargs):
if email is None:
if not 'username' in kwargs or kwargs['username'] is None:
return None
email = kwargs['username']
email = email.lower()
user_model = get_user_model()
try:
user = user_model.objects.get(email=email, is_active=True)
except user_model.DoesNotExist:
return None
if user.check_password(password):
return user
# -*- coding: utf-8 -*-
import datetime
from django.utils.translation import ugettext_lazy as _
from localflavor.us.forms import USZipCodeField
from django.db import models
class USZipModelField(models.CharField):
description = "CharField with USPostalCodeField widget"
def formfield(self, **kwargs):
# This is a fairly standard way to set up some defaults
# while letting the caller override them.
defaults = {'form_class': USZipCodeField}
defaults.update(kwargs)
return super(USZipModelField, self).formfield(**defaults)
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^earnest\.accounts\.fields\.USZipModelField"])
# -*- coding: utf-8 -*-
from django.contrib.auth.forms import AdminPasswordChangeForm as DjagnoAdminPasswordChangeForm, \
SetPasswordForm, PasswordChangeForm, \
AuthenticationForm as DjangoAuthenticationForm
from django import forms
from django.utils.translation import ugettext_lazy as _
from passwords.fields import PasswordField
from earnest.accounts.models import Account
class ValidatingSetPasswordForm(SetPasswordForm):
new_password1 = PasswordField(label=_("New password"))
new_password2 = PasswordField(label=_("New password confirm"))
class ValidatingPasswordChangeForm(PasswordChangeForm):
new_password1 = PasswordField(label=_("New password"))
new_password2 = PasswordField(label=_("New password confirmation"))
class AdminPasswordChangeForm(DjagnoAdminPasswordChangeForm):
password1 = PasswordField(label=_("New password"))
password2 = PasswordField(label=_("New password confirm"))
class RegisterUserFullForm(forms.ModelForm):
password = PasswordField(label=_("Password"))
password_confirm = PasswordField(label=_("Password confirmation"))
def __init__(self, *args, **kwargs):
super(RegisterUserFullForm, self).__init__(*args, **kwargs)
self.fields['agree_to_terms_conditions'].is_checkbox = True
self.fields['agree_to_terms_conditions'].required = True
self.fields['agree_to_terms_conditions'].initial = False
def clean_password_confirm(self):
password = self.cleaned_data.get('password')
password_confirm = self.cleaned_data.get('password_confirm')
if password != password_confirm:
raise forms.ValidationError(_("Passwords doesn't match."))
return password_confirm
def save(self, commit=True):
account = super(RegisterUserFullForm, self).save(commit=False)
account.set_password(self.cleaned_data["password"])
if commit:
account.save()
return account
class Meta:
model = Account
fields = ['email', 'gender', 'birth_year', 'password','password_confirm', 'zipcode',
'financial_institution', "agree_to_terms_conditions"]
class AdminRegisterUserFullForm(RegisterUserFullForm):
#small hack to show those fields
agree_to_terms_conditions = forms.BooleanField(required=False, initial=True)
def __init__(self, *args, **kwargs):
super(AdminRegisterUserFullForm, self).__init__(*args, **kwargs)
self.fields['agree_to_terms_conditions'].required = False
def clean(self):
cleaned_data = self.cleaned_data
cleaned_data['agree_to_terms_conditions'] = True
return cleaned_data
# -*- coding: utf-8 -*-
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from earnest.accounts.fields import USZipModelField
class AccountManager(BaseUserManager):
def create_user(self, email=None, password=None, **extra_fields):
if not email:
raise ValueError('The given email must be set')
email = AccountManager.normalize_email(email)
user = self.model(email=email,
is_staff=False, is_active=True, is_superuser=False,
**extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password, **extra_fields):
u = self.create_user(email, password, **extra_fields)
u.is_staff = True
u.is_active = True
u.is_superuser = True
u.save(using=self._db)
return u
def get_by_email(self, username):
return self.get(**{'email': username})
class Account(AbstractBaseUser, PermissionsMixin):
GENDER_CHOICES = (('male', _('Male')), ('female', _('Female')))
gender = models.CharField(_('gender'), max_length=20, choices=GENDER_CHOICES)
email = models.EmailField(_('email address'), max_length=110, unique=True)
birth_year = models.PositiveSmallIntegerField(_('birth year'), max_length=4)
zipcode = USZipModelField(_('zip'), max_length=20)
financial_institution = models.CharField(_("financial institution placeholder"), max_length=255)
date_joined = models.DateTimeField(_('date joined'), auto_now_add=True)
is_staff = models.BooleanField('staff status', default=False,
help_text='Designates whether the user can log into this admin site.')
is_active = models.BooleanField('active', default=False,
help_text='Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.')
first_name = models.CharField(_('first name'), max_length=255, blank=True)
last_name = models.CharField(_('last name'), max_length=255, blank=True)
agree_to_terms_conditions = models.BooleanField(_('Agree to terms of use'), default=True)
token = models.CharField(max_length=40, blank=True, null=True)
USERNAME_FIELD = 'email'
objects = AccountManager()
def get_by_natural_key(self, username):
return self.get(**{self.model.USERNAME_FIELD: username})
def get_full_name(self):
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
return self.first_name
def get_username(self):
return self.email
def __unicode__(self):
return self.email
class AccessHistory(models.Model):
user = models.ForeignKey(Account)
date = models.DateTimeField(_('access date'), auto_now_add=True)
ip_address = models.CharField(_('IP address'), blank=True, max_length=50)
# -*- coding: utf-8 -*-
from django.test import TestCase
from django.test.client import Client
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.forms.models import model_to_dict
from earnest.accounts.models import Account
from earnest.accounts.forms import RegisterUserFullForm, AdminRegisterUserFullForm
class AccountsTests(TestCase):
maxDiff = None
def test_index(self):
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
REGISTER_FULL_EXPECTED_FORM_FIELDS = [
'gender',
'email',
'zipcode',
'birth_year',
'financial_institution',
'agree_to_terms_conditions',
"password",
"password_confirm"]
REGISTER_FULL_ADMIN_EXPECTED_REQUIRED_FORM_FIELDS = [
'gender',
'email',
'zipcode',
'birth_year',
'financial_institution',
"password",
"password_confirm"]
REGISTER_FULL_PUBLIC_EXPECTED_REQUIRED_FORM_FIELDS = REGISTER_FULL_EXPECTED_FORM_FIELDS
VALID_USER = {
'gender': 'male',
'email': '[email protected]',
'zipcode': '94209',
'birth_year': 1984,
'financial_institution': 'placeholder',
'password': '123A124aS',
'password_confirm': '123A124aS',
'agree_to_terms_conditions': 'on',
}
def test_register_forms_confirm_password_fail(self):
form = AdminRegisterUserFullForm(data={'password': 'passwordA2', 'password_confirm': "PasswordA3"})
self.failIf(form.is_valid())
self.assertIn(_("Passwords doesn't match."), form.errors['password_confirm'])
def test_register_user_in_admin_form_fields(self):
form = AdminRegisterUserFullForm()
self.assertEqual(set(form.fields.keys()), set(self.REGISTER_FULL_EXPECTED_FORM_FIELDS))
def test_register_user_in_admin_confirm_password_success(self):
form = AdminRegisterUserFullForm(data={'password': 'passwordA2', 'password_confirm': "passwordA2"})
self.failIf(form.is_valid())
self.assertFalse(form.errors.get('password_confirm'))
def test_empty_public_registration_form(self):
#should throw all errors!
form = RegisterUserFullForm(data={})
self.failIf(form.is_valid())
self.assertEqual(set(form.errors.keys()), set(self.REGISTER_FULL_PUBLIC_EXPECTED_REQUIRED_FORM_FIELDS))
def test_empty_admin_registration_form(self):
#should throw all errors!
form = AdminRegisterUserFullForm(data={})
self.failIf(form.is_valid())
self.assertEqual(set(form.errors.keys()), set(self.REGISTER_FULL_ADMIN_EXPECTED_REQUIRED_FORM_FIELDS))
def help_test_register_forms(self):
#activate & login user
user = Account.objects.get_by_email(self.VALID_USER.get("email"))
response = self.client.login(username=self.VALID_USER.get("email"), password=self.VALID_USER.get("password"))
self.assertEqual(response, False)
user.is_active = True
user.save()
response = self.client.login(username=self.VALID_USER.get("email"), password=self.VALID_USER.get("password"))
self.assertEqual(response, True)
user_for_compare = self.VALID_USER.copy()
del user_for_compare['password']
del user_for_compare['password_confirm']
user_for_compare['agree_to_terms_conditions'] = True
user_for_compare['is_active'] = True
user_for_compare['is_superuser'] = False
user_for_compare['is_staff'] = False
user_for_compare['token'] = ''
user_for_compare['first_name'] = ''
user_for_compare['last_name'] = ''
user_from_db = model_to_dict(user)
del user_from_db['password']
del user_from_db['id']
del user_from_db['groups']
del user_from_db['user_permissions']
del user_from_db['last_login']
self.assertEqual(set(user_from_db), set(user_for_compare))
def test_valid_public_user_registration(self):
form = RegisterUserFullForm(data=self.VALID_USER)
self.assertTrue(form.is_valid())
form.save()
self.help_test_register_forms()
def test_valid_admin_user_registration(self):
form = AdminRegisterUserFullForm(data=self.VALID_USER)
#form.is_valid()
#print (form.errors.keys())
self.assertTrue(form.is_valid())
form.save()
self.help_test_register_forms()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment