Whatz up?!
The integration of django-register is awesome! But if you want to customize it with additional models it can be confusing.
Here in example I will show how to create your custom backend, form to handle it (custom validator and model choice field).
Note, the django I use is version v1.5.4 django-registration v1.0. Some line breaks are imposed due to layout of this page.
Thus, bellow you will find everything you need to:
- Create custom backend
- Add custom form
- Create custom validation
- Badabung! :D
Below is and example extending
from registration.backends.default.views.RegistrationView
First of all, inherit RegistrationView, then override register() and get_form_class() functions.
In the examples to follow it is assumed that the class is saved to regbackend.py.
#regbackend.py
from registration.backends.default.views import RegistrationView
#create custom registration backend
class StudentBackend(RegistrationView):
'''
we just want to override register and fix profile creation
'''
def register(self,request, **kwargs):
from usermanager.models import Profile
user=super(StudentBackend,self).register(request, **kwargs)
user.first_name = kwargs['first_name']
user.last_name = kwargs['last_name']
user.save()
profile = Profile.objects.create(
user=user, course=kwargs['course'])
profile.save()
def get_form_class(self, request):
"""
Return the default form class used for user registration.
"""
from usermanager.form import UserRegistrationForm
return UserRegistrationForm
Below is the code from urls.py. Nothing fancy, just import your registration backend, and form, and redirect accounts/register/ to your backend.
#urls.py
from regbackend import StudentBackend
from form import UserRegistrationForm
urlpatterns = patterns('',
url(r'^accounts/register/$',
StudentBackend.as_view(form_class = UserRegistrationForm),
name='registration_register'),
(r'^accounts/', include('registration.backends.default.urls')),
#more url configs
)
Following code is from form.py:
#form.py
from django import forms
from django.contrib.auth.models import User
from usermanager.models import Course, Profile
from registration.forms import RegistrationForm
from django.utils.translation import ugettext_lazy as _
attrs_dict = { 'class': 'required' }
#this function checks for the allowed domain:
def affiliation_valid_email(value):
allowed_domain=['domain.se','domain.se']
#not the prettiest soliution
v_error=_("Email does not match allowed domains (%s, %s)"
%(allowed_domain[0],allowed_domain[1])
if value.split('@')[1] not in allowed_domain:
raise forms.ValidationError(v_error)
else:
return value
#the registration form is inherited from django-registration
class UserRegistrationForm(RegistrationForm):
class Meta:
model = User
fields = ("first_name",
"last_name",
"username",
"email",
"password1",
"password2")
#username is enforced to some particular rules
u_error = _("User name needs to match domain convention.")
username = forms.RegexField(regex=r'^\w',
max_length=9,
widget=forms.TextInput(attrs=attrs_dict),
label=_("Username - same as in domain!"),
error_messages={
'invalid': u_error })
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
course = forms.ModelChoiceField(queryset=Course.objects,required=True)
email = forms.EmailField(validators=[affiliation_valid_email],
widget=forms.TextInput(
attrs=dict(attrs_dict,maxlength=75)
),
label=_("domain - Email address"))
def clean(self):
#clean with super
ue_error = _("Email and user name do not match.")
super(UserRegistrationForm, self).clean()
#this is just checking that username is the same as in email
if self.cleaned_data['email'].split('@')[0] ==
self.cleaned_data.get("username"):
return self.cleaned_data
else:
raise forms.ValidationError(ue_error)
def save(self, commit=True):
user = super(UserRegistrationForm, self).save(commit=True)
user.email = self.cleaned_data["email"]
user.first_name = self.cleaned_data["first_name"]
user.last_name =self.cleaned_data["last_name"]
profile = Profile(
systemuser=user, course = self.cleaned_data["course"])
if self.commit:
user.save()
profile.save()
return user
Models used in this example:
#models.py
class Course(models.Model):
code = models.CharField(max_length=6)
teacher = models.CharField(max_length=30)
class Meta:
app_label = "usermanager"
verbose_name = "Course"
verbose_name_plural = "Courses"
def __unicode__(self):
return "%s" % self.code
class Profile(models.Model):
user=models.ForeignKey(User, unique=True)
course=models.ForeignKey('usermanager.Course')
created = models.DateTimeField(auto_now_add=True)
updated_local = models.DateTimeField(blank=True, null=True)
def getCourse(self):
return "%s" %self.course
def save(self,*args,**kwargs):
self.updated_local = datetime.now()
super(Profile, self).save(*args,**kwargs)
def __unicode__(self):
return "Profile: %s" %self.user
Finally, remember to enable registration in installed apps before running
python manage.py syncdb
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'django.contrib.admindocs',
'registration',
)