<commit_before>#User Authentication
The aim of this next part of the tutorial is to get you familiar with the user authentication mechanisms provided by Django. We'll be using the `auth` app provided as part of a standard Django installation, located in in package `django.contrib.auth`. According to [Django's official documentation on Authentication](https://docs.djangoproject.com/en/1.9/topics/auth/), the application provides the following concepts and functionality.

- The concept of a *User*.
- *Permissions*, a series of binary flags (e.g. yes/no) that determine what a user may or may not do.
- *Groups*, a method of applying permissions to more than one user.
- A configurable *password hashing system*, a must for ensuring data security.
- *Forms and view tools for logging in users*, or restricting content.

There's lots that Django can do for you regarding user authentication. In this chapter, we'll be covering the basics to get you started. This will help you build your confidence with the available tools and their underlying concepts.

## Setting up Authentication
Before you can begin to play around with Django's authentication offering, you'll need to make sure that the relevant settings are present in your Rango project's `settings.py` file.

Within the `settings.py` file find the `INSTALLED_APPS` list and check that `django.contrib.auth` and `django.contrib.contenttypes` are listed, so that it looks similar to the code below:

{lang="python",linenos=off}
	INSTALLED_APPS =[
	    'django.contrib.admin',
	    'django.contrib.auth',
	    'django.contrib.contenttypes',
	    'django.contrib.sessions',
	    'django.contrib.messages',
	    'django.contrib.staticfiles',
	    'rango',
	]

While `django.contrib.auth` provides Django with access to the provided authentication system, the package `django.contrib.contenttypes` is used by the authentication app to track models installed in your database.

I> ### Migrate, if necessary!
I> If you had to add `django.contrib.auth` and `django.contrib.contenttypes` applications to your `INSTALLED_APPS` tuple, you will need to update your database with the `$ python manage.py migrate` command. This will add underlying tables to your database for you. An example would be the table for the `User` model, providing Django with a location to store details about users.
I>
I> It's generally good practice to run the `migrate` command whenever you add a new app to your Django project - the app could contain models that'll need to be synchronised to your underlying database.


## Password Hashing
Storing passwords as plaintext within a database is something which should absolutely be not done under any circumstances. If the wrong person acquired a database full of user accounts to your app, they could wreak havoc. Fortunately, Django's `auth` app by default stores a [hash of user passwords](https://en.wikipedia.org/wiki/Cryptographic_hash_function) using the [PBKDF2 algorithm](http://en.wikipedia.org/wiki/PBKDF2), providing a good level of security for your user's data.  However, if you want more control over how the passwords are hashed, you can change the approach used by Django in your project's `settings.py` module, by adding in a tuple to specify the `PASSWORD_HASHERS`. An example of this is shown below.

{lang="python",linenos=off}
	PASSWORD_HASHERS = (
		'django.contrib.auth.hashers.PBKDF2PasswordHasher',
		'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
	)

Django will pick and use the first password hasher in `PASSWORD_HASHERS` (e.g. `settings.PASSWORD_HASHERS[0]`). If other password hashers are specified in the tuple, Django will also use these if the first hasher doesn't work.

If you want to use a more secure hasher, you can install [Bcrypt](https://pypi.python.org/pypi/bcrypt/) using `pip install bcrypt`, and then set the `PASSWORD_HASHERS` to be:

{lang="python",linenos=off}
	PASSWORD_HASHERS = [
		'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
		'django.contrib.auth.hashers.BCryptPasswordHasher',
		'django.contrib.auth.hashers.PBKDF2PasswordHasher',
		'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
	]

As previously mentioned, Django uses the PBKDF2 algorithm to hash passwords by default. As such, if you do not specify a `PASSWORD_HASHERS` tuple, Django defaults to using `django.contrib.auth.hashers.PBKDF2PasswordHasher`. You can read more about password hashing in the [official Django documentation on how Django stores passwords](https://docs.djangoproject.com/en/1.9/topics/auth/passwords/#how-django-stores-passwords).


## Password Validators
As people may be tempted to enter a password that is comparatively easy to guess, a welcome new feature introduced to Django 1.9 is that of [password validation](https://docs.djangoproject.com/en/1.9/topics/auth/passwords/#password-validation). In your Django project's `settings.py` module, you will notice a list of nested dictionaries with the name `AUTH_PASSWORD_VALIDATORS`. From the nested dictionaries, you can clearly see that Django 1.9 comes with a number of pre-built password validators for common password checks, such as length. These different validators can be easily configured by specifying `OPTIONS` for each. If, for example, you wanted to ensure accepted password are at least six characters long, you can set `min_length` of the `MinimumLengthValidator` password validator to `6`. This can be seen in the example shown below.

{lang="python",linenos=off}
	AUTH_PASSWORD_VALIDATORS = [
	    ...
	    {
	        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
	        'OPTIONS': { 'min_length': 6, }
	    },
	    ...
	]
	
It is also possible to create your own password validators. Although we don't cover the creation of custom password validators in this tutorial, refer to the [official Django documentation on password validators](https://docs.djangoproject.com/en/1.9/topics/auth/passwords/#password-validation) for more information.


##The `User` Model

The core of Django's authentication system is the `User` object, located
at `django.contrib.auth.models.User`. A `User` object represents each of
the people interacting with a Django application. The [Django
documentation on User
objects](https://docs.djangoproject.com/en/1.9/topics/auth/default/#user-objects)
states that they are used to allow aspects of the authentication system
like access restriction, registration of new user profiles and the
association of creators with site content.

The `User` model has five main fields. They are:

-   the username for the user account;
-   the account's password;
-   the user's email address;
-   the user's first name; and
-   the user's surname.

The model also comes with other attributes such as `is_active`, `is_staff` , `is_superuser` which are Boolean fields to denoted whether the account is active, is owned by a staff member or has superuser privileges, respectively.  Check the
[official Django documentation on the user
model](https://docs.djangoproject.com/en/1.9/ref/contrib/auth/#django.contrib.auth.models.User)
for a full list of attributes provided by the base `User` model.

##Additional User Attributes
If you would like to include other user related attributes than what is provided by
the `User` model, then you will needed to create a model that is
associated with the the `User` model. For our Rango application, we want
to include two more additional attributes for each user account.
Specifically, we wish to include:

- a `URLField`, allowing a user of Rango to specify their own website; and
- a `ImageField`, which allows users to specify a picture for their user profile.

This can be achieved by creating an additional model in Rango's
`models.py` file. Let's add a new model called `UserProfile`:

{lang="python",linenos=off}
	class UserProfile(models.Model):
		# This line is required. Links UserProfile to a User model instance.
		user = models.OneToOneField(User)
		
		# The additional attributes we wish to include.
		website = models.URLField(blank=True)
		picture = models.ImageField(upload_to='profile_images', blank=True)
		
		# Override the __unicode__() method to return out something meaningful!
		def __unicode__(self):
			return self.user.username

Note that we reference the `User` model using a one-to-one relationship.
Since we reference the default `User` model, we need to import it within
the `models.py` file:

{lang="python",linenos=off}
	from django.contrib.auth.models import User

It may have been tempting to add these additional fields by inheriting
from the `User` model directly. However, because other applications may
also want access to the `User` model, then it not recommended to use
inheritance, but instead use the one-to-one relationship.

For Rango, we've added two fields to complete our user profile, and
provided a `__unicode__()` method to return a meaningful value when a
unicode representation of a `UserProfile` model instance is requested.

For the two fields `website` and `picture`, we have set `blank=True` for
both. This allows each of the fields to be blank if necessary, meaning
that users do not have to supply values for the attributes if they do
not wish to.

Also note that the `ImageField` field has an `upload_to` attribute. The value
of this attribute is conjoined with the project's `MEDIA_ROOT` setting
to provide a path with which uploaded profile images will be stored. For
example, a `MEDIA_ROOT` of
`<workspace>/tango_with_django_project/media/` and `upload_to` attribute
of `profile_images` will result in all profile images being stored in
the directory
`<workspace>/tango_with_django_project/media/profile_images/`.

I> ###Take the Pil
I>
I> The Django `ImageField` field makes use of the *Python Imaging Library
I> (PIL)*. If you have not done so already, install PIL via Pip with:
I> 		`pip install pillow` 
I> or 
I>		`pip install pillow --global-option="build_ext" --global-option="--disable-jpeg"`
I> if you don't have `jpeg` support.
I>
I> You can check what packages are installed in your (virtual) environment by issuing  the command, `pip list`.

To make the `UserProfile` model data accessible via the Django admin web interface add the following lines to the `admin.py` file.

{lang="python",linenos=off}
	from rango.models import UserProfile
	
	...
	
	admin.site.register(UserProfile)


I> ###Migrate
I>
I> Remember that your database must be updated with the creation of a new
I> model. Run `$ python manage.py makemigrations rango` from your
I> terminal to create the migration scripts for the new `UserProfile`
I> model. Then run `$ python manage.py migrate`

##Creating a *User Registration* View and Template

With our authentication infrastructure laid out, we can now begin to
build onto it by providing users of our application with the opportunity
to create user accounts. We can achieve this by creating a new view, template and URL mapping to handle user registration.


I> ###Django User Registration Applications
I>
I> It is important to note that there are several off-the-shelf user
I> registration applications available which reduce a lot of the hassle of
I> building your own registration and log in forms. 
I> 
I> However it is good idea to get a feeling for the underlying mechanics before using such
I> applications so that you have some sense of what is going on under the hood.
I> It will also re-enforce your understanding of working
I> with forms, how to extend upon the user model, and how to upload media (which can cause a lot of grief).

To provide the user registration functionality we will go through the
following steps:

1.  Create a `UserForm` and `UserProfileForm`.
2.  Add a view to handle the creation of a new user.
3.  Create a template that displays the `UserForm` and `UserProfileForm`.
4.  Map a URL to the view created.
5.  Link the index page to the register page<commit_msg>Working on user authentication<commit_after>#User Authentication
The aim of this next part of the tutorial is to get you familiar with the user authentication mechanisms provided by Django. We'll be using the `auth` app provided as part of a standard Django installation, located in in package `django.contrib.auth`. According to [Django's official documentation on Authentication](https://docs.djangoproject.com/en/1.9/topics/auth/), the application provides the following concepts and functionality.

- The concept of a *User*.
- *Permissions*, a series of binary flags (e.g. yes/no) that determine what a user may or may not do.
- *Groups*, a method of applying permissions to more than one user.
- A configurable *password hashing system*, a must for ensuring data security.
- *Forms and view tools for logging in users*, or restricting content.

There's lots that Django can do for you regarding user authentication. In this chapter, we'll be covering the basics to get you started. This will help you build your confidence with the available tools and their underlying concepts.

## Setting up Authentication
Before you can begin to play around with Django's authentication offering, you'll need to make sure that the relevant settings are present in your Rango project's `settings.py` file.

Within the `settings.py` file find the `INSTALLED_APPS` list and check that `django.contrib.auth` and `django.contrib.contenttypes` are listed, so that it looks similar to the code below:

{lang="python",linenos=off}
	INSTALLED_APPS =[
	    'django.contrib.admin',
	    'django.contrib.auth',
	    'django.contrib.contenttypes',
	    'django.contrib.sessions',
	    'django.contrib.messages',
	    'django.contrib.staticfiles',
	    'rango',
	]

While `django.contrib.auth` provides Django with access to the provided authentication system, the package `django.contrib.contenttypes` is used by the authentication app to track models installed in your database.

I> ### Migrate, if necessary!
I> If you had to add `django.contrib.auth` and `django.contrib.contenttypes` applications to your `INSTALLED_APPS` tuple, you will need to update your database with the `$ python manage.py migrate` command. This will add underlying tables to your database for you. An example would be the table for the `User` model, providing Django with a location to store details about users.
I>
I> It's generally good practice to run the `migrate` command whenever you add a new app to your Django project - the app could contain models that'll need to be synchronised to your underlying database.


## Password Hashing
Storing passwords as plaintext within a database is something which should absolutely be not done under any circumstances. If the wrong person acquired a database full of user accounts to your app, they could wreak havoc. Fortunately, Django's `auth` app by default stores a [hash of user passwords](https://en.wikipedia.org/wiki/Cryptographic_hash_function) using the [PBKDF2 algorithm](http://en.wikipedia.org/wiki/PBKDF2), providing a good level of security for your user's data.  However, if you want more control over how the passwords are hashed, you can change the approach used by Django in your project's `settings.py` module, by adding in a tuple to specify the `PASSWORD_HASHERS`. An example of this is shown below.

{lang="python",linenos=off}
	PASSWORD_HASHERS = (
		'django.contrib.auth.hashers.PBKDF2PasswordHasher',
		'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
	)

Django considers the order of hashers specified as important, and will pick and use the first password hasher in `PASSWORD_HASHERS` (e.g. `settings.PASSWORD_HASHERS[0]`). If other password hashers are specified in the tuple, Django will also use these if the first hasher doesn't work.

If you want to use a more secure hasher, you can install [Bcrypt](https://pypi.python.org/pypi/bcrypt/) using `pip install bcrypt`, and then set the `PASSWORD_HASHERS` to be:

{lang="python",linenos=off}
	PASSWORD_HASHERS = [
		'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
		'django.contrib.auth.hashers.BCryptPasswordHasher',
		'django.contrib.auth.hashers.PBKDF2PasswordHasher',
		'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
	]

As previously mentioned, Django uses the PBKDF2 algorithm to hash passwords by default. As such, if you do not specify a `PASSWORD_HASHERS` tuple, Django defaults to using the `django.contrib.auth.hashers.PBKDF2PasswordHasher` password hasher. You can read more about password hashing in the [official Django documentation on how Django stores passwords](https://docs.djangoproject.com/en/1.9/topics/auth/passwords/#how-django-stores-passwords).


## Password Validators
As people may be tempted to enter a password that is comparatively easy to guess, a welcome new feature introduced to Django 1.9 is that of [password validation](https://docs.djangoproject.com/en/1.9/topics/auth/passwords/#password-validation). In your Django project's `settings.py` module, you will notice a list of nested dictionaries with the name `AUTH_PASSWORD_VALIDATORS`. From the nested dictionaries, you can clearly see that Django 1.9 comes with a number of pre-built password validators for common password checks, such as length. These different validators can be easily configured by specifying `OPTIONS` for each. If, for example, you wanted to ensure accepted password are at least six characters long, you can set `min_length` of the `MinimumLengthValidator` password validator to `6`. This can be seen in the example shown below.

{lang="python",linenos=off}
	AUTH_PASSWORD_VALIDATORS = [
	    ...
	    {
	        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
	        'OPTIONS': { 'min_length': 6, }
	    },
	    ...
	]
	
It is also possible to create your own password validators. Although we don't cover the creation of custom password validators in this tutorial, refer to the [official Django documentation on password validators](https://docs.djangoproject.com/en/1.9/topics/auth/passwords/#password-validation) for more information.


##The `User` Model
The `User` object (located at `django.contrib.auth.models.User`) is considered to be the core of Django's authentication system. A `User` object represents each of the individuals interacting with a Django application. The [Django documentation on User objects](https://docs.djangoproject.com/en/1.9/topics/auth/default/#user-objects) states that they are used to allow aspects of the authentication system like access restriction, registration of new user profiles, and the association of creators with site content.

The `User` model has five key attributes. They are:

-   the *username* for the user account;
-   the account's *password*;
-   the user's *email address*;
-   the user's *first name*; and
-   the user's *surname*.

The `User` model also comes with other attributes such as `is_active`, `is_staff` and `is_superuser` which are boolean fields to denote whether the account is active, is owned by a staff member, or has superuser privileges - respectively.  Check out the [official Django documentation on the user model](https://docs.djangoproject.com/en/1.9/ref/contrib/auth/#django.contrib.auth.models.User) for a full list of attributes provided by the base `User` model.

##Additional `User` Attributes
If you would like to include other user related attributes than what is provided by the `User` model, you will needed to create a model that is *associated* with the the `User` model. For our Rango app, we want to include two more additional attributes for each user account. Specifically, we wish to include:

- a `URLField`, allowing a user of Rango to specify their own website; and
- a `ImageField`, which allows users to specify a picture for their user profile.

This can be achieved by creating an additional model in Rango's `models.py` file. Let's add a new model called `UserProfile`:

{lang="python",linenos=off}
	class UserProfile(models.Model):
	    # This line is required. Links UserProfile to a User model instance.
	    user = models.OneToOneField(User)
	    
	    # The additional attributes we wish to include.
	    website = models.URLField(blank=True)
	    picture = models.ImageField(upload_to='profile_images', blank=True)
	    
	    # Override the __unicode__() method to return out something meaningful!
        # Remember if you use Python 2.7.x, define __unicode__ too!
	    def __str__(self):
	        return self.user.username

Note that we reference the `User` model using a one-to-one relationship. Since we reference the default `User` model, we need to import it within the `models.py` file:

{lang="python",linenos=off}
	from django.contrib.auth.models import User

For Rango, we've added two fields to complete our user profile, and provided a `__str__()` method to return a meaningful value when a unicode representation of a `UserProfile` model instance is requested. Remember, if you are using Python 2, you'll also need to provide a `__unicode__()` method to return a unicode variant of the user's username.

For the two fields `website` and `picture`, we have set `blank=True` for both. This allows each of the fields to be blank if necessary, meaning that users do not have to supply values for the attributes.

Furthermore, it should be noted that the `ImageField` field has an `upload_to` attribute. The value of this attribute is conjoined with the project's `MEDIA_ROOT` setting to provide a path with which uploaded profile images will be stored. For example, a `MEDIA_ROOT` of `<workspace>/tango_with_django_project/media/` and `upload_to` attribute of `profile_images` will result in all profile images being stored in the directory `<workspace>/tango_with_django_project/media/profile_images/`.

I> Why about Inheriting to Extend?
I> It may have been tempting to add the additional fields defined above by inheriting from the `User` model directly. However, because other applications may also want access to the `User` model, it not recommended to use inheritance - but instead use a one-to-one relationship within your database instead.

I> ### Take the PIL
I>
I> The Django `ImageField` field makes use of the *Python Imaging Library (PIL)*. If you have not done so already, install PIL via Pip with the command `pip install pillow`. If you don't have `jpeg` support enabled, you can also install PIL with the command `pip install pillow --global-option="build_ext" --global-option="--disable-jpeg"`.
I>
I> You can check what packages are installed in your (virtual) environment by issuing the command `pip list`.

To make the `UserProfile` model data accessible via the Django admin Web interface, add the following lines to the `admin.py` file.

{lang="python",linenos=off}
	from rango.models import UserProfile
	...
	admin.site.register(UserProfile)


I> ### Once again, Migrate!
I> Remember that your database must be updated with the creation of a new model. Run `$ python manage.py makemigrations rango` from your terminal or Command Prompt to create the migration scripts for the new `UserProfile` model. Then run `$ python manage.py migrate` to execute the migration which creates the associated tables within the underlying database.

##Creating a *User Registration* View and Template

With our authentication infrastructure laid out, we can now begin to
build onto it by providing users of our application with the opportunity
to create user accounts. We can achieve this by creating a new view, template and URL mapping to handle user registration.


I> ###Django User Registration Applications
I>
I> It is important to note that there are several off-the-shelf user
I> registration applications available which reduce a lot of the hassle of
I> building your own registration and log in forms. 
I> 
I> However it is good idea to get a feeling for the underlying mechanics before using such
I> applications so that you have some sense of what is going on under the hood.
I> It will also re-enforce your understanding of working
I> with forms, how to extend upon the user model, and how to upload media (which can cause a lot of grief).

To provide the user registration functionality we will go through the
following steps:

1.  Create a `UserForm` and `UserProfileForm`.
2.  Add a view to handle the creation of a new user.
3.  Create a template that displays the `UserForm` and `UserProfileForm`.
4.  Map a URL to the view created.
5.  Link the index page to the register page
{'fraction_non_alphanumeric': 0.07181844297615628, 'fraction_numerical': 0.003160011490950876, 'mean_word_length': 4.582588774341351, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 60, 'https://': 16, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6974620', 'n_tokens_mistral': 6674, 'n_tokens_neox': 6314, 'n_words': 3222}