This tutorial is a series of tutorials, with a directory index at the beginning of each tutorial for ease of reading:

  • Basic setup
  • Extending the User model
  • registered
  • The login
  • Logout and page hopping
  • Change the password
  • Customize the authentication background

User registration is to create user objects and save the user’s personal information to a database. Reviewing djangos classic MVT development process, the user registration function starts with creating a user model (M), which we’ve already done. Write the registered view function (V) and bind the corresponding URL to the view function. Write a registration template (T) that provides a registration form to the user. The Django user system has built-in views for logging in, changing passwords, and retrieving passwords. However, the only view function not provided is the user registration view function.

Write user registration forms

Django has built a User registration form: the Django. Contrib. The auth. Forms. UserCreationForm, but the form of a small problem is that it is associated with Django’s built-in User model, can be seen from its source code:

class UserCreationForm(forms.ModelForm):.class Meta:
        model = User
        fields = ("username",)
        field_classes = {'username': UsernameField}Copy the code

The problem is that the model property of the inner class Meta, whose value corresponds to auth.user, cannot be used in our custom User model. The good news is that the form is really just a Python class, so we can inherit it with a few minor changes.

The form code is usually written in forms.py, so create a new forms.py file under the Users application to hold the form code, and write the following code:

users/forms.py

from django.contrib.auth.forms import UserCreationForm
from .models import User

class RegisterForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = User
        fields = ("username"."email")Copy the code

The Model attribute under the Meta inner class of UserCreationForm corresponds to the Auth.user model. RegisterForm overrides the value of its parent model property to users.user.

In addition, fields are used to specify the fields of the form that will be rendered as form controls in the template (i.e., some form controls). The UserCreationForm only specifies fields = (“username”,), that is, the username, and the password and confirmation password are specified in the UserCreationForm properties. Therefore, the default form rendering only has the username (username), password, confirm password three form controls. We also want users to provide an email address when they register, so we added an email field in fields.

Note: Although the value of the model property is both specified as User, one is auth.user and the other is users.user.

Write the user registration view function

Let’s first examine the logic of the registration function. The user fills in the registration information in the registration form and submits the information to the server through the form. The view function extracts the user’s registration information from the data submitted by the user and then verifies the validity of the data. If the data is valid, a new user object is created and the user’s data is saved to the database, otherwise an error message is returned to the user, prompting the user to modify the submitted information. The process is as simple as that, and here is the corresponding code (the view function code is usually written in views.py) :

users/views.py

from django.shortcuts import render, redirect
from .forms import RegisterForm

def register(request):
    The user has submitted the registration information only if the request is POST
    if request.method == 'POST':
        # request.POST is a dictionary-like data structure that records user-submitted registration information
        Username, password, email address
        Use this data to instantiate a user registration form
        form = RegisterForm(request.POST)

        Verify the validity of the data
        if form.is_valid():
            If submitting data is legal, call the form's save method to save the user data to the database
            form.save()

            If you have registered successfully, go back to home page
            return redirect('/')
    else:
        The request is not a POST, indicating that the user is visiting the registration page, showing the user an empty registration form
        form = RegisterForm()

    # Render template
    If the user is visiting the registration page, an empty registration form is rendered
    If the user submits registration information through the form, but the data validation is not valid, a form with an error message will be rendered
    return render(request, 'users/register.html', context={'form': form})Copy the code

Note that the above view is a classic flow for working with forms, namely:

def form_process_view(request):
    if request.method == 'POST':
        The request is POST, which constructs a data-bound form from the data submitted by the user
        form = Form(request.POST)

        if form.is_valid():
             Form data is valid
            # Other processing...
            # jump
            return redirect('/')
    else:
        # request is not POST, construct an empty form
        form = Form()

    # Render template
    If it is not a POST request, an empty form is rendered
    If the user submits data through the form, but the data validation is not valid, then the form is rendered with an error message
    return render(request, 'template.html', context={'form': form})Copy the code

The above logical code can be applied to various forms with minor modifications.

Setting THE URL Mode

View functions need to be bound to the corresponding URL, so that when a user accesses a URL, Django knows which view function to call to handle the request. Start by creating a new urls.py file under the Users app to set the URL mode for the registered view function.

users/urls.py

from django.conf.urls import url
from . import views

app_name = 'users'
urlpatterns = [
    url(r'^register/', views.register, name='register'),]Copy the code

App_name = ‘users’ sets the namespace for the urls module. If you do not understand the Settings of URL mode, please refer to the relevant basic tutorial.

The next step is to include the URL schema for the Users application in the project’s urls.py file. Open the urls.py file under django_auth_example/ and include users.urls.py:

django_auth_example/urls.py

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    Don't forget to include the include function at the top
    url(r'^users/', include('users.urls')),]Copy the code

Write the registration page template

We rendered users/register.html in the view function, but the template file does not currently exist, so we will create it now. I like to put templates files in the templates/ directory at the root of my project (manage.py), and then create templates/ folders with the same name as the application to store the template files for that application. Of course, it doesn’t matter where the template is located, depending on the project, just configure the template path so That Django can find the template file.

Set the template directory structure

As is my custom, create a templates/ directory at the root of your project (manage.py), and then create a Users directory under templates/ to store the template files for the Users application. Then create a new register. HTML template file under the Users/directory. The directory structure changes to:

django_auth_example/
    manage.py
    django_auth_example/
        __init__.py
        settings.py
        urls.py
        wsgi.py
    templates/
        users/
            register.htmlCopy the code

Configuring template Paths

Then you need to set the templates/ path in settings.py. Go to settings.py and find the templates option, which looks like this:

django_auth_example/settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates'.'DIRS': [].'APP_DIRS': True.'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug'.'django.template.context_processors.request'.'django.contrib.auth.context_processors.auth'.'django.contrib.messages.context_processors.messages',],},},]Copy the code

Where DIRS is the path to set the template, write os.path.join(BASE_DIR, ‘templates’) in [], as follows:

django_auth_example/settings.py

TEMPLATES = [
    {
        ...
        'DIRS': [os.path.join(BASE_DIR, 'templates')],... },]Copy the code

In this case, BASE_DIR is the variable defined by settings.py before the start of the configuration and records the value of the project root directory django_auth_example/ (note the outermost django_auth_example/ directory). In this directory is the templates/ directory for the template file, so connect the two paths using os.path.join to make a complete template path that Django knows to look for.

Render the registration form

The next step is to render the form in the register.html template as follows:

templates/users/register.html 


      
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0, the maximum - scale = 1.0, user - scalable = no">
    <title>registered</title>
    <link rel="stylesheet" href="https://unpkg.com/mobi.css/dist/mobi.min.css">
    <style>
        .errorlist {
            color: red;
        }
    </style>
</head>
<body>
<div class="flex-center">
    <div class="container">
        <div class="flex-center">
            <div class="unit-1-2 unit-1-on-mobile">
                <h3>registered</h3>
                <form class="form" action="{% url 'users:register' %}" method="post">
                    {% csrf_token %}
                    {% for field in form %}
                        {{ field.label_tag }}
                        {{ field }}
                        {{ field.errors }}
                        {% if field.help_text %}
                            <p class="help text-small text-muted">{{ field.help_text|safe }}</p>
                        {% endif %}
                    {% endfor %}
                    <button type="submit" class="btn btn-primary btn-block">registered</button>
                </form>
                <div class="flex-center top-gap text-small">
                    <a href="login.html">Login with an existing account</a>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>Copy the code

To make the registration page more aesthetically pleasing, I introduced mobi.css to provide styling support. Ignore the rest of the code and focus on the form part:

<form class="form" action="{% url 'users:register' %}" method="post">
  {% csrf_token %}
  {% for field in form %}
    {{ field.label_tag }}
    {{ field }}
    {{ field.errors }}
    {% if field.help_text %}
        <p class="help text-small text-muted">{{ field.help_text|safe }}</p>
    {% endif %}
  {% endfor %}
  <button type="submit" class="btn btn-primary btn-block">registered</button>
</form>Copy the code

When using forms in Django, note the following:

  • Set the action property of the form. In this case, the form’s data is submitted to the URL/Users /register/, and Django calls the corresponding view functionregisterProcess. Here we use the {% URL %} template tag to prevent url hardcoding. For the {% URL %} template tag, see the introduction in this articleBlog post details page.
  • Set the method property of the form. Usually the form data is submitted via post.
  • Add the {% cSRF_Token %} template tag to the form. The purpose of this template tag is to prevent cross-site request forgery attacks and improve site security. As for what cross-site request forgery is, those interested can search for relevant information and refer to it. Just remember to add {% cSRF_Token %} template tags to forms whenever you use them, or Django won’t allow you to submit form data.

Next comes the control part of the form. For the form form (this is a template variable that is an instance of RegisterForm, which we pass to the template in the Register view function). Loop through to get the form’s various controls:

  • {{field.label_tag}} is the label label of the corresponding control
  • {{field}} is the corresponding form control
  • {{field.errors}} is a form error (if any)
  • {{field. Help_text | safe}} is related with the help of information control

For example, the RegisterForm form has a username field and renders the form controls as follows:

<label for="id_username">User name:</label><! {{field.label_tag}} -->
<input type="text" name="username" id="id_username" autofocus required maxlength="150" /><! {{field}} -->
<p class="help text-small text-muted">Mandatory. 150 characters or less. Contains letters, digits, and only @/./+/-/_ symbols.</p><! -- Corresponding to {{field.help_text}} -->Copy the code

You can click F12 to see the source code of the form and compare which parts of the form control are rendered. This form rendering is a common practice, and you can use it as a template that can be modified to work with other templates that need to render forms.

OK, run development server, visit http://127.0.0.1:8000/users/register/, you can see the render of the user registration form.

User registration Form

You can try registering a user, or try typing something wrong on purpose, and see what the form renders as an error message. For example, I typed two different passwords on purpose and got an error message:

An error message is displayed indicating two inconsistent passwords

Check whether the user is successfully registered on the Admin background

If there are no errors in the form data, it will jump to the front page after submitting the form, and since we didn’t write any view functions to handle the front page, we get a 404 error. But it doesn’t matter, we now only care about whether the user registered successfully. So how to check whether the user has registered successfully? You can go to the Django Admin background to see if there is any data for a user’s new registration. In order to view user data in the Admin background, you first need to register the user model. Open the users/admin.py file and register the users.user model in it:

users/admin.py

from django.contrib import admin
from .models import User

admin.site.register(User)Copy the code

To get into the background, you also need to create a super administrator user. Create an administrator account using Python manage.py createsuperuser. If you don’t know how, follow the instructions in the Django Admin post.

Browser enter http://127.0.0.1:8000/admin/, login administrator account, can check to the registered user information, such as in my background can see three users:

Information about newly registered users

One of these is the administrator account created using the createsuperuser command, and the other two are registered new users.

At this point, the registration function is complete. After the user registers, he must log in. The next step is how to provide the user login function.

conclusion

The sample project code for this tutorial is located at GitHub: Django Auth Example.

If you have problems, please ask for help in the following ways.

  • Leave a comment in the Comments section of Djangos User Authentication System: Register.
  • Post a detailed description of the problem in the Django section of Pythonzhcn.

For more Django tutorials, visit my personal blog, Dreamers Blog.