cradmin_authenticate — Login/logout views

The purpose of the cradmim.apps.cradmin_authenticate app is to provide a general purpose login/logout workflow.

It is designed to work with any user model that uses and email and a password for login.

Install

Add the following to INSTALLED_APPS:

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

And add something like this to your root url config:

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

Configure

Required settings:
LOGIN_REDIRECT_URL
The default URL to redirect to after login unless you provide a next-attribute as input to the view (see Where to redirect after login).
Optional settings:
DJANGO_CRADMIN_FORGOTPASSWORD_URL
If this is set, we show a forgot password link on the login page.
DJANGO_CRADMIN_USE_EMAIL_AUTH_BACKEND
If this is set (True), we explicitly use email to login, not USERNAME_FIELD. This will also work with the standard django user model.

How it works

We determine the username field from the USERNAME_FIELD attribute of the user model. As long as the username field is email or username, and you use password to login, the view should just work out of the box.

You can extend django_cradmin.apps.cradmin_authenticate.views.LoginView and add a custom login form class by overriding the get_form_class-method.

Where to redirect after login

You can change the LOGIN_REDIRECT_URL setting as documented above if you want to change the default URL to redirect to after login. If login is part of a workflow where you just want users to login before they continue to the next step, you can use the next querystring parameter. Example:

<a href="{% url 'cradmin-authenticate-login' %}?next=/comments/add">
    Add comment
</a>

Where to redirect after logout

Just like with the login view, you can supply a next querystring attribute to the logout view. This can be used for workflows like login as another user:

<a href="{% url 'cradmin-authenticate-logout' %}?next={% url 'cradmin-authenticate-login' %}">
    Login as another user
</a>

Nesting “next” redirects

You can nest next — you just have to url quote correctly.

Lets say you want to add an add comment as another user button. This means that you want to logout, login, and then redirect to the add comment view, which we for this example assume is at /comments/add. This would look something like this in a template:

<a href="{% url 'cradmin-authenticate-logout' %}?next={% url 'cradmin-authenticate-login' %}%3Fnext%3D%2Fcomments%2Fadd">
    Add comment as another user
</a>

The %<number><letter> stuff is URL escape codes. You will most likely want to handle this using python code. Lets generate the same URL using Python:

from django.utils.http import urlencode
from django.core.urlresolvers import reverse

login_url = '{login_url}?{arguments}'.format(
    login_url=reverse('cradmin-authenticate-login'),
    arguments=urlencode({
        'next': '/comments/add'
    })
)
logout_url = '{logout_url}?{arguments}'.format(
    logout_url=reverse('cradmin-authenticate-logout'),
    arguments=urlencode({
        'next': login_url
    })
)

Views and their names

The app provides the following two views:

cradmin-authenticate-login
The view named cradmin-authenticate-login is used for login.
cradmin-authenticate-logout
The view named cradmin-authenticate-logout is used for logging users out.

Customization

The authentication-view is handled by the django_cradmin.apps.cradmin_authenticate.views.login.LoginView in combination with the various subclasses of django_cradmin.apps.cradmin_authenticate.views.login.AbstractLoginForm.

If you want to customize the default behaviour, extend/override the suitable class from these:

django_cradmin.apps.cradmin_authenticate.views.login

class AbstractLoginForm(*args, **kwargs)

Bases: django.forms.forms.Form

Superclass for the various Login-forms used by LoginView by default. Known subclasses:

username_field = None

The field used with the password for authentication. Must be set in subclasses

username_field_placeholder = None

The placeholder text for the username field. Must be set in subclasses

password_field_placeholder = 'Password'

The placeholder text for the password field. Must be set in subclasses

error_message_invalid_login = None

Error message to show if username and password do not match

error_message_inactive = 'This account is inactive.'

Error message to show if the account is inactive.

password = None

The password field

authenticate(**kwargs)

Wrapper around django.contrib.auth.authenticate to make it easy for subclasses to add extra kwargs.

clean()

validate the form, and execute django.contrib.auth.authenticate() to login the user if form is valid.

class UsernameLoginForm(*args, **kwargs)

Bases: django_cradmin.apps.cradmin_authenticate.views.login.AbstractLoginForm

This form is used for username-based login.

Using this form in its default state requires the User-models USERNAME_FIELD to be username. This is set in the field username_field in this class.

class EmailLoginForm(*args, **kwargs)

Bases: django_cradmin.apps.cradmin_authenticate.views.login.AbstractLoginForm

This form is used for email-based login along with the django_cradmin.apps.cradmin_authenticate.backends.EmailAuthBackend.

This requires adding DJANGO_CRADMIN_USE_EMAIL_AUTH_BACKEND = True to your settings.py.

This will work with the default django User-model, and your own custom User model, as long as your User model has the field email for login. If your email field is called something else, you will need to override the username_field attribute of this class.

If you want to use this class without the EmailAuthBackend, you should rather use the EmailLoginFormNoSanityCheck.

class EmailLoginFormNoSanityCheck(*args, **kwargs)

Bases: django_cradmin.apps.cradmin_authenticate.views.login.EmailLoginForm

This works exactly like EmailLoginForm, but does not require DJANGO_CRADMIN_USE_EMAIL_AUTH_BACKEND to be set.

class LoginView(**kwargs)

Bases: django_cradmin.viewhelpers.formview.formview.StandaloneFormView

View for handling login. By default, a “forgot password” link is read from DJANGO_CRADMIN_FORGOTPASSWORD_URL to your settings.py.

Constructor. Called in the URLconf; can contain helpful extra keyword arguments, and other things.

get_form_class()

Determine which subclass of AbstractLoginForm should be used for login.

if settings.DJANGO_CRADMIN_USE_EMAIL_AUTH_BACKEND is set, the EmailLoginForm will be used. If not, the user_model.USERNAME_FIELD will be checked, and EmailLoginFormNoSanityCheck will be used if this is email, and UsernameLoginForm if it is set to username.

Override this function to add your own login-form.

get(*args, **kwargs)

if user is authenticated, redirect to settings.LOGIN_REDIRECT_URL, else render the login form.

get_initial_email_value()

Can be overriden to provide an initial value for the email.

If this returns anything other than None, it changes the behavior of the form to focus on the password field instead of the email field at page load, and the email field becomes a hidden field instead of an input field.

See also

initial_email_value().

Returns:The initial email value if we have any. Should return something that evaluates to bool(value) == False if we have no initial email value.
initial_email_value

We use this to retrieve the value of get_initial_email_value(), and you should use it if you need the value in your subclasses.

This method only retrieves the value returned by get_initial_email_value() once, and cache it internally. This means that the get_initial_email_value method can perform potentially expensive operations, or operations that should only run once (like request.session.pop) without worrying about it.

get_success_url()

Returns the redirect-url after login-success. This will either be the next field in request.GET if present, or settings.LOGIN_REDIRECT_URL if not.

form_valid(form)

Run django.contrib.auth.login() once the login-form was validated.

get_context_data(**kwargs)

adds form from get_form_helper(), and (if set) settings.DJANGO_CRADMIN_FORGOTPASSWORD_URL to template-context.

django_cradmin.apps.cradmin_authenticate.backends

class EmailAuthBackend

Bases: object

Custom Authentication backend for using email as your login-field on any User-model. This will also work with the default django User-model, as it does not require USERNAME_FIELD to be email.

authenticate(email, password)

Find the User corresponding to email, verify password and return user.

NOTE: this function is defined by Django as required for an Auth-backend

Parameters:
  • emailemail for the user to authenticate
  • passwordpassword for the user to authenticate
Returns:

the User if authentication was successful, or None if not.

get_user(user_id)

locate and return a User based on the primary key of the current User model.

NOTE: this function is defined by Django as required for an Auth-backend

Parameters:user_id – the id of a User
Returns:the User matching the given user_id if it exists, None if not.