I’ve had a read of this
http://docs.b-list.org/django-registration/0.8/backend-api.html
and i’ve had a shot at making my own backend. I am doing this because I want to create a backend that disallows having the same email used for registration, and I wanted to change the email-error message. I also wanted to add in my own field!
Here is what I came up with:
from django import forms
from registration.forms import RegistrationForm
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from registration.forms import attrs_dict
class customRegistrationForm(RegistrationForm):
email2 = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict,
maxlength=75)),
label=_("Confirm email"))
def clean_email(self):
"""
Validate that the email is alphanumeric and is not already
in use.
"""
try:
email = User.objects.get(email__iexact=self.cleaned_data['email'])
except User.DoesNotExist:
return self.cleaned_data['email']
raise forms.ValidationError(_("That email already exists - if you have forgotten your password, go to the login screen and then select \"forgot password\""))
def clean(self):
"""
Verifiy that the values entered into the two email fields
match. Note that an error here will end up in
``non_field_errors()`` because it doesn't apply to a single
field.
"""
if 'email' in self.cleaned_data and 'email2' in self.cleaned_data:
if self.cleaned_data['email'] != self.cleaned_data['email2']:
raise forms.ValidationError(_("The two email fields didn't match."))
return super(RegistrationForm,clean)
The above goes in my init.py file (whetever that is)
Then, I have in my urls.py code:
url(r'^accounts/register/$',
register,
{ 'backend': 'myapp.forms.customRegistrationForm' },
name='registration_register'),
... #other urls here!
Now, when i go to the /accounts/register page, I get the following error:
AttributeError at /accounts/register/
‘customRegistrationForm’ object has no attribute ‘registration_allowed’
Which is weird. It seems to be telling me I need a "registration_allowed" method added to my subclass. BUT, the subclass is a subclass of the RegistrationForm, which works fine and doesn’t have that stuff defined… I know I can add these members in, but it seems to beat the purpose of extension, right?
UPDATE
Here is the code now that it works!
I broke up the varying classes into varying init.py files in different folders – one called "forms" and one called "backends", both of which sit in a folder "djangoRegistration" under my main project.
/forms/init.py
from django import forms
from registration.forms import RegistrationForm
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from registration.forms import attrs_dict
class customRegistrationForm(RegistrationForm):
def __init__(self, *args, **kw):
super(RegistrationForm, self).__init__(*args, **kw)
self.fields.keyOrder = [
'username',
'email',
'email2',
'password1',
'password2'
]
email2 = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict,
maxlength=75)),
label=_("Confirm email"))
def clean_email(self):
"""
Validate that the email is alphanumeric and is not already
in use.
"""
try:
email = User.objects.get(email__iexact=self.cleaned_data['email'])
except User.DoesNotExist:
return self.cleaned_data['email']
raise forms.ValidationError(_("That email already exists - if you have forgotten your password, go to the login screen and then select \"forgot password\""))
def clean(self):
"""
Verifiy that the values entered into the two email fields
match. Note that an error here will end up in
``non_field_errors()`` because it doesn't apply to a single
field.
"""
if 'email' in self.cleaned_data and 'email2' in self.cleaned_data:
if self.cleaned_data['email'] != self.cleaned_data['email2']:
raise forms.ValidationError(_("The two email fields didn't match."))
return super(RegistrationForm,clean)
/backends/init.py
from registration.backends.default import DefaultBackend
from dumpstownapp.djangoRegistration.forms import customRegistrationForm
class customDefaultBackend(DefaultBackend):
def get_form_class(self, request):
"""
Return the default form class used for user registration.
"""
return customRegistrationForm
and finally, my urls.py just references the new backend:
url(r'^accounts/register/$',
register,
{ 'backend': 'myapp.djangoRegistration.backends.customDefaultBackend' },
name='registration_register'),
#more urls here! yay!
As a final note, I had to add some code to "order" the way the fields were presented, which is what the init method in the customRegistrationForm is doing
thanks!
You’re trying to use a form as a backend, but that’s not what a backend is at all. As the document you link to explains, a backend is a class that implements certain methods, including
registration_allowed. The form doesn’t implement any of those, which is not surprising, because it’s meant for user input and validation, not the backend actions.However, that page does give a hint as to the correct way to implement this. One of the methods that the backend can define is
get_form_class(), which returns the form class to use. So, it seems that what you need is a custom backend that inherits fromregistration.backends.default.DefaultBackendand overrides just theget_form_classmethod, which simply returnscustomRegistrationForm.