cradmin_register_account — A register account workflow

The purpose of the django_cradmin.apps.cradmin_register_account app is to provide a general purpose register account workflow where all you need to do is provide a form class.

It is designed to work with any user model, and we provide out of the box ready to use form classes for the default Django user model, and for custom user models with email and password.

Install

This app requires the following apps:

In addition to the changes required by the apps listed above, add the following to INSTALLED_APPS:

INSTALLED_APPS = (
    # ...
    'django_cradmin.apps.cradmin_register_account',
)

And add something like this to your root url config:

urlpatterns = patterns(
    # ...
    url(r'^register/', include('django_cradmin.apps.cradmin_register_account.urls')),
    # ...
)

Quickstart

Set the DJANGO_CRADMIN_SITENAME setting to the name of your site:

DJANGO_CRADMIN_SITENAME = 'Testsite'

Set the LOGIN_URL or DJANGO_CRADMIN_REGISTER_ACCOUNT_REDIRECT_URL setting to the URL you want your users to go to after the user is created and activated:

DJANGO_CRADMIN_REGISTER_ACCOUNT_REDIRECT_URL = '/authenticate/login'

Set the DJANGO_CRADMIN_REGISTER_ACCOUNT_FORM_CLASS setting to a register account form class compatible with your user model:

If you are using the default django.contrib.auth.models.User model:

DJANGO_CRADMIN_REGISTER_ACCOUNT_FORM_CLASS = \
    'django_cradmin.apps.cradmin_register_account.forms.auth_user.AuthUserCreateAccountForm'

If you have a custom user model with an email-field and a set_password()-method, you can use:

DJANGO_CRADMIN_REGISTER_ACCOUNT_FORM_CLASS = \
    'django_cradmin.apps.cradmin_register_account.forms.email.EmailUserCreateAccountForm'

If your user model does not fit with any of these descriptions, or for more details, continue reading this document.

Now you should be able to visit http://localhost:8000/register/begin to register a new user.

Configure

Required settings:
DJANGO_CRADMIN_SITENAME
The name of the site.
DJANGO_CRADMIN_REGISTER_ACCOUNT_REDIRECT_URL or LOGIN_URL

The URL to redirect to after login is found in the following order:

  1. Via the next-attribute as input to the view (see Where to redirect after the account has been created).
  2. Use the DJANGO_CRADMIN_REGISTER_ACCOUNT_REDIRECT_URL setting if defined.
  3. Use the LOGIN_URL setting.

This means that you have to set one of the settings in order for the workflow to work out of the box.

DJANGO_CRADMIN_REGISTER_ACCOUNT_FORM_CLASS

Must be set to the full Python path to a Django ModelForm that handles input and saving of new users. We provide default implementations for the default Django user model, and an implementation usable with many custom user models.

See Register account form for details.

How it works

Step One — Create an inactive user

The first step is to create a user object. This is taken care of by the view named cradmin-register-account-begin. This view displays and validate/process the form configured via the DJANGO_CRADMIN_REGISTER_ACCOUNT_FORM_CLASS setting.

Step two — Activate the account

Uses the cradmin_activate_account app.

Register account form

The register account forms are just normal Django ModelForm subclasses. They must provide:

  • Layout via Django crispy forms layouts.
  • Validation.
  • A save method that sets the user as inactive and it should most likely set a usable password unless you use an authentication backend that sets passwords in some other way.

To make this easier, we provide some classes you can extend or use.

If you use django.contrib.auth.models.User, the following form classes can be used without any modification, or as base class for your own register account form class:

In the django_cradmin.apps.cradmin_register_account.forms.auth_user_form module:

AuthUserCreateAccountForm A create account form for auth_user.
AuthUserCreateAccountAutoUsernameForm A create account form for auth_user that autocreates the username from the email.

If you have a custom user model, you may be able to use the following form classes without any modification, or as base class for your own register account form class:

In the django_cradmin.apps.cradmin_register_account.forms.auth_user_form module:

EmailUserCreateAccountForm A create account form for a custom user model with an email field and a set_password()-method.

If you want to create a completely custom register account form, you will most likely want to extend one of these abstract form classes:

In the django_cradmin.apps.cradmin_register_account.forms.base module:

AbstractCreateAccountForm Base class for account creation forms.
AbstractCreateAccountWithPasswordForm Extends AbstractCreateAccountForm with the typical password + repeat password fields.

Form classes for django.contrib.auth.models.User

The following forms are available in django_cradmin.apps.cradmin_register_account.forms.auth_user. They provide ready-to-use register account forms suitable if your user model is django.contrib.auth.models.User. They can also be used as base classes for your own register account forms.

class AuthUserCreateAccountForm(*args, **kwargs)

Bases: django_cradmin.apps.cradmin_register_account.forms.base.AbstractCreateAccountWithPasswordForm

A create account form for auth_user.

Can be used directly as the DJANGO_CRADMIN_REGISTER_ACCOUNT_FORM_CLASS setting, or extended to create a custom register account form.

To use it directly, set the following setting:

DJANGO_CRADMIN_REGISTER_ACCOUNT_FORM_CLASS = \
    'django_cradmin.apps.cradmin_register_account.forms.auth_user.AuthUserCreateAccountForm'

The form only includes username, email and password. To add more fields, simply override the Meta-class and the field layout. Lets say we want to make a form that includes the first_name and last_name fields:

from django_cradmin.apps.cradmin_register_account.forms.auth_user import AuthUserCreateAccountForm

class AuthUserCreateAccountWithFullNameForm(AuthUserCreateAccountForm):
    class Meta(AuthUserCreateAccountForm.Meta):
        fields = ['email', 'username', 'first_name', 'last_name']

    def get_field_layout(self):
        return [
            'username',
            'email',
            'first_name',
            'last_name',
            'password1',
            'password2',
        ]
get_field_renderables()

Get field renderables.

Must be overridden in subclasses.

Returns:List of django_cradmin.uicontainer.container.AbstractContainerRenderable.
Return type:list
class AuthUserCreateAccountAutoUsernameForm(*args, **kwargs)

Bases: django_cradmin.apps.cradmin_register_account.forms.auth_user.AuthUserCreateAccountForm

A create account form for auth_user that autocreates the username from the email.

This is a subclass of AuthUserCreateAccountForm, and the examples for extending that class works for this class too.

Can be used directly as the DJANGO_CRADMIN_REGISTER_ACCOUNT_FORM_CLASS setting, or extended to create a custom register account form.

To use it directly, set the following setting:

DJANGO_CRADMIN_REGISTER_ACCOUNT_FORM_CLASS = \
    'django_cradmin.apps.cradmin_register_account.forms.auth_user.AuthUserCreateAccountAutoUsernameForm'
set_extra_user_attributes(user)

Override this to set extra user attributes in addition to deactivate_user() and set_password().

get_field_renderables()

Get field renderables.

Must be overridden in subclasses.

Returns:List of django_cradmin.uicontainer.container.AbstractContainerRenderable.
Return type:list

Form classes for custom user models

The following forms are available in django_cradmin.apps.cradmin_register_account.forms.email. They provide ready-to-use register account forms suitable if your user model has an email-field and a set_password()-method. They can also be used as base classes for your own register account forms.

class EmailUserCreateAccountForm(*args, **kwargs)

Bases: django_cradmin.apps.cradmin_register_account.forms.base.AbstractCreateAccountWithPasswordForm

A create account form for a custom user model with an email field and a set_password()-method.

Can be used directly as the DJANGO_CRADMIN_REGISTER_ACCOUNT_FORM_CLASS setting, or extended to create a custom register account form.

To use it directly, set the following setting:

DJANGO_CRADMIN_REGISTER_ACCOUNT_FORM_CLASS = \
    'django_cradmin.apps.cradmin_register_account.forms.email.EmailUserCreateAccountForm'

The form only includes username, email and password. To add more fields, simply override the Meta-class and the field layout. Lets say we want to make a form that includes the full_name field:

from django_cradmin.apps.cradmin_register_account.forms.auth_user import EmailUserCreateAccountForm

class AuthUserCreateAccountWithFullNameForm(EmailUserCreateAccountForm):
    class Meta(EmailUserCreateAccountForm.Meta):
        fields = ['username', 'full_name']

    def get_field_renderables(self):
        field_renderables = super(AuthUserCreateAccountWithFullNameForm).get_field_renderables()
        field_renderables.insert(0, uicontainer.fieldwrapper.FieldWrapper(fieldname='full_name))
        return field_renderables
get_field_renderables()

Get field renderables.

Must be overridden in subclasses.

Returns:List of django_cradmin.uicontainer.container.AbstractContainerRenderable.
Return type:list

Abstract register account form classes

The following base forms are available in django_cradmin.apps.cradmin_register_account.forms.base. They provide a common structure for all the register account forms.

class AbstractCreateAccountForm(*args, **kwargs)

Bases: django.forms.models.ModelForm

Base class for account creation forms.

Subclasses must override:

get_submit_button_label()

Returns the submit button label.

Override this to provide a custom label.

set_password(user)

Set the password of the given user.

Must be overridden in subclasses.

Should not save the user, only set the password.

Typically this will retrieve the password from the form, or generate a password, and set the password using user.set_password. Example:

class MyCreateAccountForm(AbstractCreateAccountForm):
    ...
    def set_password(self, user):
        raw_password = 'secret'  # or self.cleaned_data['password']
        user.set_password(raw_password)
set_extra_user_attributes(user)

Override this to set extra user attributes in addition to deactivate_user() and set_password().

set_extra_user_attributes_before_clean(user)

Override this to set extra user attributes before the any cleaning is run on the user instance.

get_field_renderables()

Get field renderables.

Must be overridden in subclasses.

Returns:List of django_cradmin.uicontainer.container.AbstractContainerRenderable.
Return type:list
get_form_renderable()

Get a django_cradmin.renderable.AbstractRenderable that renders the form.

This will typically be a uicontainer — HTML builder with form support tree containing a django_cradmin.uicontainer.form.Form, but it can be any AbstractRenderable. Not using a django_cradmin.uicontainer.form.Form (or a subclass of it) is fairly complex when it comes to handling error messages and form rendering, so it is generally not recommended.

Returns:The renderable object.
Return type:django_cradmin.renderable.AbstractRenderable
save(commit=True)

Save this form’s self.instance object if commit=True. Otherwise, add a save_m2m() method to the form which can be called after the instance is saved manually at a later time. Return the model instance.

class AbstractCreateAccountWithPasswordForm(*args, **kwargs)

Bases: django_cradmin.apps.cradmin_register_account.forms.base.AbstractCreateAccountForm

Extends AbstractCreateAccountForm with the typical password + repeat password fields. Validates that the passwords match.

Subclasses must override:

  • deactivate_user().
password1 = None

The first password.

password2 = None

The repeat password fields.

set_password(user)

Set the password of the user using user.set_password(...).

Does not save the user.

clean()

Validate the form.

The default implementation validates that the passwords match.

Make sure to call super if you override this:

class MyCreateAccountForm(AbstractCreateAccountWithPasswordForm):
    ...
    def clean(self):
        cleaned_data = super(MyCreateAccountForm, self).clean()
        # ...
        return cleaned_data

Where to redirect after the account has been created

You can change the DJANGO_CRADMIN_REGISTER_ACCOUNT_REDIRECT_URL or LOGIN_URL settings as documented above if you want to change he default URL to redirect to after the account has been created.

If account creation is part of a workflow where you just want users to register a user before they continue to the next step, you can use the next querystring parameter. Example:

<a href="{% url 'cradmin-register-account-begin' %}?next=/account/edit/details">
    Create account
</a>