# The model-based activation workflow

This workflow implements a two-step – registration, followed by activation – process for user signup.

Note

Use of the model-based workflow is discouraged

The model-based activation workflow was originally the only workflow built in to `django-registration`, and later was the default one. However, it no longer represents the best practice for registration with modern versions of Django, and so it continues to be included only for backwards compatibility with existing installations of `django-registration`.

If you’re setting up a new installation and want a two-step process with activation, it’s recommended you use the HMAC activation workflow instead.

Also, note that this workflow was previously found in `registration.backends.default`, and imports from that location still function in `django-registration` 2.0 but now raise deprecation warnings. The correct location going forward is `registration.backends.model_activation`.

## Default behavior and configuration

To make use of this workflow, simply add `registration` to your `INSTALLED_APPS`, run `manage.py migrate` to install its model, and include the URLconf `registration.backends.model_activation.urls` at whatever location you choose in your URL hierarchy. For example:

    from django.conf.urls import include, url

    urlpatterns = [
        # Other URL patterns ...
        url(r'^accounts/', include('registration.backends.model_activation.urls')),
        # More URL patterns ...
    ]

This workflow makes use of the following settings:

- `ACCOUNT_ACTIVATION_DAYS`
- `REGISTRATION_OPEN`

By default, this workflow uses `registration.forms.RegistrationForm` as its form class for user registration; this can be overridden by passing the keyword argument `form_class` to the registration view.

Two views are provided: `registration.backends.model_activation.views.RegistrationView` and `registration.backends.model_activation.views.ActivationView`. These views subclass `django-registration`‘s base `RegistrationView` and `ActivationView`, respectively, and implement the two-step registration/activation process.

Upon successful registration – not activation – the user will be redirected to the URL pattern named `registration_complete`.

Upon successful activation, the user will be redirected to the URL pattern named `registration_activation_complete`.

This workflow uses the same templates and contexts as the HMAC activation workflow, which is covered in the quick-start guide. Refer to the quick-start guide for documentation on those templates and their contexts.

## How account data is stored for activation

During registration, a new instance of the user model (by default, Django’s `django.contrib.auth.models.User` – see the custom user documentation for notes on using a different model) is created to represent the new account, with the `is_active` field set to `False`. An email is then sent to the email address of the account, containing a link the user must click to activate the account; at that point the `is_active` field is set to `True`, and the user may log in normally.

Activation is handled by generating and storing an activation key in the database, using the following model:

class `registration.models.``RegistrationProfile`

  A simple representation of the information needed to activate a new user account. This is not a user profile; it simply provides a place to temporarily store the activation key and determine whether a given account has been activated.

  Has the following fields:

  `user`

    A `OneToOneField` to the user model, representing the user account for which activation information is being stored.

  `activation_key`

    A 40-character `CharField`, storing the activation key for the account. Initially, the activation key is the hex digest of a SHA1 hash; after activation, this is reset to `ACTIVATED`.

  Additionally, one class attribute exists:

  `ACTIVATED`

    A constant string used as the value of `activation_key` for accounts which have been activated.

  And the following methods:

  `activation_key_expired`()

    Determines whether this account’s activation key has expired, and returns a boolean (`True` if expired, `False` otherwise). Uses the following algorithm:

    1. If `activation_key` is `ACTIVATED`, the account has already been activated and so the key is considered to have expired.
    2. Otherwise, the date of registration (obtained from the `date_joined` field of `user`) is compared to the current date; if the span between them is greater than the value of the setting `ACCOUNT_ACTIVATION_DAYS`, the key is considered to have expired.

    Return type: | bool

  `send_activation_email`(site)

    Sends an activation email to the address of the account.

    The activation email will make use of two templates: `registration/activation_email_subject.txt` and `registration/activation_email.txt`, which are used for the subject of the email and the body of the email, respectively. Each will receive the following context:

    `activation_key`
      The value of `activation_key`.
    `expiration_days`
      The number of days the user has to activate, taken from the setting `ACCOUNT_ACTIVATION_DAYS`.
    `site`
      An object representing the site on which the account was registered; depending on whether `django.contrib.sites` is installed, this may be an instance of either `django.contrib.sites.models.Site` (if the sites application is installed) or `django.contrib.sites.models.RequestSite` (if not). Consult the documentation for the Django sites framework for details regarding these objects’ interfaces.

    Note that, to avoid header-injection vulnerabilities, the rendered output of `registration/activation_email_subject.txt` will be forcibly condensed to a single line.

    Parameters: | site (`django.contrib.sites.models.Site` or `django.contrib.sites.models.RequestSite`) – An object representing the site on which account was registered.
    Return type: | `None`

Additionally, `RegistrationProfile` has a custom manager (accessed as `RegistrationProfile.objects`):

class `registration.models.``RegistrationManager`

  This manager provides several convenience methods for creating and working with instances of `RegistrationProfile`:

  `activate_user`(activation_key)

    Validates `activation_key` and, if valid, activates the associated account by setting its `is_active` field to `True`. To prevent re-activation of accounts, the `activation_key` of the `RegistrationProfile` for the account will be set to `RegistrationProfile.ACTIVATED` after successful activation.

    Returns the user instance representing the account if activation is successful, `False` otherwise.

    Parameters: | activation_key (string, a 40-character SHA1 hexdigest) – The activation key to use for the activation.
    Return type: | user or bool

  `delete_expired_users`()

    Removes expired instances of `RegistrationProfile`, and their associated user accounts, from the database. This is useful as a periodic maintenance task to clean out accounts which registered but never activated.

    Accounts to be deleted are identified by searching for instances of `RegistrationProfile` with expired activation keys and with associated user accounts which are inactive (have their `is_active` field set to `False`). To disable a user account without having it deleted, simply delete its associated `RegistrationProfile`; any `User` which does not have an associated `RegistrationProfile` will not be deleted.

    A custom management command is provided which will execute this method, suitable for use in cron jobs or other scheduled maintenance tasks: `manage.py cleanupregistration`.

    Return type: | `None`

  `create_inactive_user`(username, email, password, site[, send_email])

    Creates a new, inactive user account and an associated instance of `RegistrationProfile`, sends the activation email and returns the new `User` object representing the account.

    Parameters:

    - username (string) – The username to use for the new account.
    - email (string) – The email address to use for the new account.
    - password (string) – The password to use for the new account.
    - site (`django.contrib.sites.models.Site` or `django.contrib.sites.models.RequestSite`) – An object representing the site on which the account is being registered.
    - send_email (bool) – If `True`, the activation email will be sent to the account (by calling `RegistrationProfile.send_activation_email()`). If `False`, no email will be sent (but the account will still be inactive).

    Return type: | user

  `create_profile`(user)

    Creates and returns a `RegistrationProfile` instance for the account represented by `user`.

    The `RegistrationProfile` created by this method will have its `activation_key` set to a SHA1 hash generated from a combination of the account’s username and a random salt.

    Parameters: | user (`User`) – The user account; an instance of `django.contrib.auth.models.User`.
    Return type: | `RegistrationProfile`