Search code examples
pythondjangodjango-registration

Django-registration with custom backend: how to return error message on register()


I'm using a custom backend (subclassed django-registration's SimpleBackend). I override the register() method, because I need to do some processing during the registration (for example, communicate with external services).

In case the registration fails, can I tell the registration form an error occurred?

Does this need to be implemented at the form validation level?

As another example, a database error could happen at user creation. How can the registration gracefully fail?

EDIT: Here is my subclass of SimpleBackend:

class MySimpleBackend(SimpleBackend):
    def register(self, request, **kwargs):
        username, email, password = kwargs['username'], kwargs['email'], kwargs['password1']

        # 
        # Make a call to some external API, for example
        retval = api_call_to_somewhere()
        if retval is False:
            # Request failed: display some error message on registration form
            return something
            # OR
            raise some_other

        # Rest of code is the same as django-registration

        User.objects.create_user(username, email, password)

        # authenticate() always has to be called before login(), and
        # will return the user we just created.
        new_user = authenticate(username=username, password=password)
        login(request, new_user)
        signals.user_registered.send(sender=self.__class__,
                                     user=new_user,
                                     request=request)
        return new_user

Solution

  • I ended up customizing django-registration's register view, from registration.views (not to be confused with SimpleBackend.register method)

    The original view calls backend.register() if form.is_valid(), and then redirects to the success URL, so it assumes a user is created in backend.register(), not catching any exception. Adding my own code to catch exceptions, I can raise errors on backend.register() and display them to the user, as a form error.

    Below is the code as it appears on django-registration\registration\views, in the middle of register function, with the lines I added:

    if request.method == 'POST':
        form = form_class(data=request.POST, files=request.FILES)
        if form.is_valid():
            try:  # added this line
                new_user = backend.register(request, **form.cleaned_data)
                if success_url is None:
                    to, args, kwargs = backend.post_registration_redirect(request, new_user)
                    return redirect(to, *args, **kwargs)
                else:
                    return redirect(success_url)
            # added these 3 lines below
            except Exception, err:
                errors = form._errors.setdefault(NON_FIELD_ERRORS, ErrorList())
                errors.append(err)