10
votes

django-registration 1.0 now has support for django 1.5 custom user models. The django-registration documentation only has the following FAQ item about it:

I’m using Django 1.5 and a custom user model; how do I make that work?

Although the two built-in backends supplied with django-registration both assume Django’s default User model, the base view classes are deliberately user-model-agnostic. Simply subclass them, and implement logic for your custom user model.

I'm not sure which views I need to subclass and what should go in them. I've also noticed that the ProfileManager in django-registration still assumes a separate username field.

In my specific case, I've removed the 'username' field, added a 'display_name', and made 'email' the identifying field:

class MyUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(
        verbose_name="Email Address",
        max_length=384,
        unique=True,
        db_index=True,)
    display_name = models.CharField(max_length=128, blank=True)
    date_joined = models.DateTimeField(default=timezone.now)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'

    def get_full_name(self):
        return self.email

    def get_short_name(self):
        return self.email

    def __unicode__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True

    @property
    def is_staff(self):
        return self.is_admin

Without subclassing any django-registration classes, the default rendering of the registration form pulls in fields from User instead of MyUser.

I've seen the following SO thread django-registration app and Django 1.5 custom user model, but it didn't help.

Update

I've noticed that RegistrationForm is hardcoded with a 'username' field. The FAQ only mentions subclassing the backend, so I'm not sure what the intention is here. Should I subclass the form as well?

1
Please have a look at this commit - bitbucket.org/LinnTroll/django-registration-1.5/commits/… !! You need to subclass DefaultBackend, RegistrationFormFromUserModel as well as RegistrationManager for this.pankaj28843
Have you changed AUTH_USER_MODEL to the new custom user model in settings.py?Wei
What'd you end up doing? I'm thinking about just handling this but explicitly defining the fields in the registration form instead of just using the form template tag. Not ideal, but I think it might be the simplest option.bnjmn
i just performed a find and replace for the particular application and replaced all instances with my custom user model and fields. Not elegant but I found it fairly effectivesj7
@jon did you find the solution. I am having similar problem. can you post what you did to make it work? ThankseagertoLearn

1 Answers

1
votes

Some parts are most definitely not Django 1.5 compatible yet: https://bitbucket.org/ubernostrum/django-registration/src/8f242e35ef7c004e035e54b4bb093c32bf77c29f/registration/forms.py?at=default#cl-48

class RegistrationForm(forms.Form):
    # ...

    def clean_username(self):
        # ...
        # The line below needs fixing
        existing = User.objects.filter(username__iexact=self.cleaned_data['username'])
        if existing.exists():
            raise forms.ValidationError(_("A user with that username already exists."))
        else:
            return self.cleaned_data['username']

So unless those methods are changed and/or you subclass them, it won't work yet.

For your specific case this registration form should do the trick:

from registration import forms as registration_forms
from django.contrib import auth

class RegistrationForm(registration_forms.RegistrationForm):
    def clean_username(self):
        '''
        Validate that the username is alphanumeric and is not already
        in use.
        '''
        User = auth.get_user_model()
        existing = User.objects.filter(display_name__iexact=self.cleaned_data['username'])
        if existing.exists():
            raise forms.ValidationError(_("A user with that name already exists."))
        else:
            return self.cleaned_data['username']

In addition to a custom property on your model:

class MyUser(AbstractBaseUser, PermissionsMixin):
    # ...

    def get_username(self):
        return self.display_name

    def set_username(self, username):
        self.display_name = username

    def del_username(self):
        del self.display_name

    username = property(get_username, set_username, del_username)