Search code examples
pythondjangodjango-registration

django-registration seems to be shortening hashed password when using subclassed RegistrationView


I'm trying to setup django-registration form with an extra field or two. I've read the documentation and scoured StackOverflow. I'm getting a problem where the user is registered with the new fields but when I try and login it doesn't recognise the password.

I've created a new view (I've just cut and pasted register from django-registration because I just want it running initially):

class MyRegistrationView (RegistrationView):
    form_class = UserRegForm

    def register(self, form):
        new_user = RegistrationProfile.objects.create_inactive_user(
            form,
            site=get_current_site(self.request)
        )
        signals.user_registered.send(sender=self.__class__,
                                     user=new_user,
                                     request=self.request)
        return new_user

It uses this form:

class UserRegForm(RegistrationForm):
    CHOICES = Institution.objects.all().order_by('name')

    institution=forms.ChoiceField(choices=( (x.id, x.name) for x in CHOICES ),
                                  required = True)

These are the additional models:

class Institution(models.Model):
    name = models.CharField(max_length=200)

    def __unicode__(self):
        return u'%s' % (self.name)

class UserProfile(models.Model):
    user=models.OneToOneField(User, on_delete=models.CASCADE)
    institution=models.ForeignKey(
        Institution,
        null=True,
        blank=True)

    def __unicode__(self):
        return u'%s' % (self.user)

My URL

url(r'^register', views.MyRegistrationView.as_view(form_class=UserRegForm), name='registration_register'),

And I've added this to save the data: from models import UserProfile from forms import UserRegForm

def user_created(sender, user, request, **kwargs):
    form = UserRegForm(request.POST)

    try: data = UserProfile.objects.get(user=user)
    except: data = UserProfile(user=user)
    data.institution = form.data["institution"]
    data.save()

from registration.signals import user_registered
user_registered.connect(user_created)

Everything works in that the user is registered, an email is sent out, the institution is saved to the UserProfile, but when I try and login using the new user (having activated the account) it tells me the username and password don't match.

When I look at the database the hashed paasword string seems to be 10 characters shorter than the admins (setup using manage.py createsuperuser) so I am doing something I shouldn't or not doing something I should.

Help would be much appreciated.


Solution

  • I solved this by basically copying all of RegistrationView into MyRegistrationView. The login now works are well. I'm not sure why this was necessary.

    from registration.backends.model_activation.views import RegistrationView
    from registration.models import RegistrationProfile
    from registration import signals
    from django.contrib.sites.shortcuts import get_current_site
    from django.core import signing
    from django.template.loader import render_to_string
    from django.conf import settings
    REGISTRATION_SALT = getattr(settings, 'REGISTRATION_SALT', 'registration')
    
    class MyRegistrationView (RegistrationView):
        form_class = UserRegForm
        email_body_template = 'registration/activation_email.txt'
        email_subject_template = 'registration/activation_email_subject.txt'
    
        def register(self, form):
            new_user = self.create_inactive_user(form)
            signals.user_registered.send(sender=self.__class__,
                                         user=new_user,
                                         request=self.request)
            return new_user
    
        def get_success_url(self, user):
            return ('registration_complete', (), {})
    
        def create_inactive_user(self, form):
            """
            Create the inactive user account and send an email containing
            activation instructions.
    
            """
            new_user = form.save(commit=False)
            new_user.is_active = False
            new_user.save()
    
            self.send_activation_email(new_user)
    
            return new_user
    
        def get_activation_key(self, user):
            """
            Generate the activation key which will be emailed to the user.
    
            """
            return signing.dumps(
                obj=getattr(user, user.USERNAME_FIELD),
                salt=REGISTRATION_SALT
            )
    
        def get_email_context(self, activation_key):
            """
            Build the template context used for the activation email.
    
            """
            return {
                'activation_key': activation_key,
                'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
                'site': get_current_site(self.request)
            }
    
        def send_activation_email(self, user):
            """
            Send the activation email. The activation key is simply the
            username, signed using TimestampSigner.
    
            """
            activation_key = self.get_activation_key(user)
            context = self.get_email_context(activation_key)
            context.update({
                'user': user
            })
            subject = render_to_string(self.email_subject_template,
                                       context)
            # Force subject to a single line to avoid header-injection
            # issues.
            subject = ''.join(subject.splitlines())
            message = render_to_string(self.email_body_template,
                                       context)
            user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
    

    Remaining issue is it just reloads the Registration page rather than going to registration complete?