Building the user registration view

Now, with the index view deployed and ready for use, let's move on to building a more complicated view where we allow the users to register on BugZot.

The following code implements a view known as UserRegisterView, which will allow the users to register to BugZot.

'''
File: user_registration.py
Description: The file contains the definition for the user registration
view allowing new users to register to the BugZot.
'''
from bugzot.application import app, brcypt, db
from bugzot.models import User, Role
from flask.views import MethodView
from datetime import datetime
from flask import render_template, session


class UserRegistrationView(MethodView):
"""User registration view to allow new user registration.

The user registration view allows for the registering of the new users
to the bugzot bug tracking system. The view allows the application
to render the user registration page along with the handling of the
submitted data.
"""

__keys = ['username', 'password', 'confirm_password', 'email']

def get(self):
"""HTTP GET handler."""

username = session.get('username', None)

# Check if there is an active user session
if username is None:
return render_template('user/registration.html')

return render_template('index/index.html', logged_in=True, username=username)

def post(self):
"""HTTP POST handler."""

form_data = {}

# Iterate over the form to validate the existence of all the
# required keys and store their data
for form_key in self.__keys:
if not request.form.has_key(form_key):
return "All fields are required"
else:
form_data[form_key] = request.form.get(form_key)

# Validate if the passwords match
if not self.__validate_passwords(form_data['password'], form_data['confirm_password']):
return "Passwords do not match"

# Generate a new model
user = self.__generate_model(form_data)

# Save the model to the database
db.session.add(user)
db.session.commit()

return render_template("user/registration_success.html")


def __generate_model(self, form_data):
"""Generate the user data model.

Returns:
db.Model
"""

username = form_data['username']
email = form_data['email']
password = bcrypt.generate_password_hash(form_data['password']).decode('utf-8')

# Determine the user role and id
role = Role.query.filter(role_name='user').first()
joining_date = datetime.now()
last_login = datetime.now()

user = User(username=username, email=email, password=password, role=role, joining_date=joining_date, last_login=last_login)
return user


def __validate_passwords(self, password, confirm_password):
"""Validate if the passwords match or not.

Returns:
Boolean
"""
if password != confirm_password:
return False
return True

With this, we finish the implementation of the user registration view. So, let's take a look at a few things that we did differently here.

The first and the foremost thing inside UserRegistrationView is the fact that the view contains the definitions for two different methods, namely, get() and post().

This is done for a purpose. To handle the user registration, we have two options at our disposal:

  1. Create separate views for rendering the user registration form and processing the registration data.
  2. Handle the form rendering and data processing in the same view based upon the type of requested.

For the registration view, we sided up with the second option to avoid the unnecessary complexity of adding two different endpoints just to handle the user registration. Also, this keeps the logically related functionalities under the same view.

For us, the get() method is responsible for rendering the user registration form when the user navigates to the registration page in their browser. When the user has filled up the data and clicks submit, the form sends the data to the same URL endpoint, but this time, as a POST request, which is handled by the post() method of the view.

Our get() user method is a simple method that checks if there is an existing user session going on the machine, and, if one is found, we redirect back to the index page, not allowing the user to re-register. If no active user session is found, the registration page is rendered.

Now, coming to our post() method, things become a little bit interesting (as a matter of fact, all the form data processing is being handled here). So, let's take a look at what this method is doing.

The first thing that happens here is, we check if the form data we got contains all the required keys or not. This is done by validating the request.form, which is a type of dictionary containing the required keys, or not. In Flask, this is done by calling the has_key() method of the request.form, which takes in the name of the key to be checked and returns true if it is found, and false otherwise.

If the keys are found, we store the keys in a local dictionary for later processing.

Once this is done, the next thing is to validate if the passwords match or not, which is done so that the user does not accidentally input an incorrect password that they might not remember in the future, causing them the added pain of going through the password reset process.

If the passwords are validated correctly, we then move on to the generation of the data model. Most of the data model generation is pretty straightforward, except the setting of the role field in the user model. Since the role field maps to the roles model in our application, we need to provide it with the correct value; otherwise, the database will report a constraint violation when we try to save the data model to the database.

By default, when a new user signs up, we assign that user the category of the user. To retrieve the user role, we can simply search by the name of the role and take the first object as our correct output. We assume here that the database returns only a single object for the query, as can be figured out from the following statement:

role = Role.query.filter(role_name='user').first()

With this, we get our role field figured out for storing into our user model.

Once our model definition is built, all we need to do is to add it to our database session and commit it. This is done through the following statements:

db.session.add(user)
db.session.commit()

Once we have successfully committed the model to the database, we can now render a success page telling the user the next steps for activating their account.

Similarly, we can now work on the development of the other models and views for the application.

For the complete code base and assisting documentation for the application, please head towards the online repository for the book, where you can learn more about the other design choices we have taken to build the application and how they work.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.142.194