Creating The Sign Up Page Part II

Welcome again. We will wrap up the sign up page by continuing from where we left off - that is creating the template. If you haven't checked out the previous part, go ahead and do that.

Alright folks, let's get to it.

As we remember in the last part of the series we set the template_name attribute of our RegisterView class to be users/register.html. So let's go ahead and create an html file inside that directory which is users/templates/users/

  • In Django, when submitting forms we use csrf_token template tag in our html file. CSRF stands for Cross Site Request Forgery. Learn more about this attack from this wikepedia page.

  • Here in our template we can access the form variable we passed into the context of RegisterView simply by using {{ form }}. But this will display everything all at once making it look hideous.

  • To render the form fields manually, we can use

{{ form.name_of_field }} For example, if we want to render the email field we can say form.email.

What about rendering form validation error messages?

Here we have to make sure we take care of any errors and display them nicely to our users.

{% if form.errors %}
    <div class="alert alert-danger alert-dismissible" role="alert">
        <div id="form_errors">
            {% for key, value in form.errors.items %}
                <strong>{{ value }}</strong>
            {% endfor %}
        </div>
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
{% endif %}
  • What the above snippet does is first check if there is an error, then loop through the errors, and display the error message in a bootstrap alert.

register.html

{% extends "users/base.html" %}
{% block title %} Register Page {% endblock title%}
{% block content %}
    <div class="form-content my-3 p-3">
        <div class="container">
            <div class="row justify-content-center">
                <div class="col-lg-7">
                    <div class="card shadow-lg border-0 rounded-lg mt-0 mb-5">
                        <div class="card-header justify-content-center">
                            <h3 class="font-weight-light my-4 text-center">Create Account</h3>
                        </div>
                        <div class="card-body">
                            <form method="POST">
                                {% csrf_token %}
                                {% if form.errors %}
                                    <div class="alert alert-danger alert-dismissible" role="alert">
                                        <div id="form_errors">
                                            {% for key, value in form.errors.items %}
                                                <strong>{{ value }}</strong>
                                            {% endfor %}
                                        </div>
                                        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                                            <span aria-hidden="true">&times;</span>
                                        </button>
                                    </div>
                                {% endif %}
                                <div class="form-row">
                                    <div class="col-md-6">
                                        <div class="form-group">
                                            <label class="small mb-1">First Name</label>
                                            {{ form.first_name }}
                                        </div>
                                    </div>
                                    <div class="col-md-6">
                                        <div class="form-group">
                                            <label class="small mb-1">Last Name</label>
                                            {{ form.last_name }}
                                        </div>
                                    </div>
                                </div>
                                <div class="form-row">
                                    <div class="col-md-6">
                                        <div class="form-group">
                                            <label class="small mb-1">Username</label>
                                            {{ form.username }}
                                        </div>
                                    </div>
                                    <div class="col-md-6">
                                        <div class="form-group">
                                            <label class="small mb-1">Email</label>
                                            {{ form.email }}
                                        </div>
                                    </div>
                                </div>
                                <div class="form-row">
                                    <div class="col-md-6">
                                        <div class="form-group">
                                            <label class="small mb-1">Password</label>
                                            {{ form.password1 }}
                                            {{ form.errors.password }}
                                        </div>
                                    </div>
                                    <div class="col-md-6">

                                        <div class="form-group">
                                            <label class="small mb-1">Confirm Password</label>
                                            {{ form.password2 }}
                                        </div>
                                    </div>
                                </div>
                                <div class="form-group mt-4 mb-0">
                                    <button type="submit" class="col-md-12 btn btn-dark">Sign Up</button><br><br>
                                </div>
                            </form>
                        </div>
                        <div class="card-footer text-center">
                            <div class="small">
                                <a href="#">Have an account? Go to Sign in</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
{% endblock content %}
  • I used bootstrap cards to render the form fields nicely.

Remember in the last part inside our RegisterView, we created a flash message to be displayed when a user is successfully created. So we need a template to display this message and the best place to put this is in base.html because every other template extends from it.

{% if messages %}
  <div class="alert alert-dismissible" role="alert">
    {% for message in messages %}
      <div class="alert alert-{{ message.tags }}">{{ message }}</div>
    {% endfor %}
    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
{% endif %}
  • What the above snippet does is first check if there is any message and if there is, it loops through them and display the messages with their respective bootstrap tags(for instance if we said message.success in our view, the bootstrap alert will be alert-success).

Oh and there is one more thing to do. Remember in the last part we used an id for the password fields so that we can use a plugin to show/hide password. The best place to put this plugin is inside base.html because we might use it again in other templates.

There are only 2 modifications we need to make.

  1. Include font awesome icons
  2. Include the Javascript plugin

base.html

<!doctype html>
<html lang="en">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <!--Font awesome icons -->
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css" integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" crossorigin="anonymous">



    <title>{% block title %} {% endblock %} </title>
</head>
<body>
  <div class="container p-3 my-3">
    <div class="row">
      <div class="col-md-12">
        <nav class="navbar navbar-expand-md navbar-light " style="background-color: #f0f5f5">
          <a href="/" class="navbar-brand">Home</a>
            <button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbarCollapse">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarCollapse">
                <div class="navbar-nav ml-auto">
                  <a href="#" class="nav-item nav-link">Profile</a>
                  <a href="#" class="nav-item nav-link">Logout</a>
                  <a href="#" class="nav-item nav-link">Sign in</a>
                </div>
            </div>
        </nav>
        <!--Any flash messages pop up in any page because this is the base template-->
        {% if messages %}
          <div class="alert alert-dismissible" role="alert">
            {% for message in messages %}
              <div class="alert alert-{{ message.tags }}">{{ message }}</div>
            {% endfor %}
            <button type="button" class="close" data-dismiss="alert" aria-label="Close">
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
        {% endif %}
        {% block content %}{% endblock %}
      </div>
    </div>
  </div>

    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>

<!-- A plugin for password show/hide  -->
   <script src="https://unpkg.com/[email protected]/dist/bootstrap-show-password.min.js"></script>

</body>
</html>

That's it for the sign up page. Now let's see if everything works.

  • Create a super user for the site if you haven't already with python manage.py createsuperuser
  • Then start your development server with python manage.py runserver.
  • Go to the http://localhost:8000/register/ and check if everything works
  • If you pass the validations, you should be redirected to the home page with a flash message.
  • Go to the admin panel to check if it created the user successfully.

Thanks for your time. You can find the finished app in github. See you next time with another part of the series.

Any comments and suggestions are welcome.

26