Skip to main content

How to add a register endpoint to the REST API

Registering users sounds like a conceptually very difficult thing, but let's break it down into steps:

  • Receive username and password from the client (as JSON).
  • Check if a user with that username already exists.
  • If it doesn't...
    • Encrypt the password.
    • Add a new UserModel to the database.
    • Return a success message.

Boilerplate set-up for a blueprint with Flask-Smorest

First, we need our imports and blueprint set-up. This is the same for pretty much every Flask-Smorest blueprint, so you already know how to do it!

resources/user.py
from flask.views import MethodView
from flask_smorest import Blueprint, abort
from passlib.hash import pbkdf2_sha256

from db import db
from models import UserModel
from schemas import UserSchema


blp = Blueprint("Users", "users", description="Operations on users")

Creating the UserRegister resource

Now let's create the MethodView class, and register a route to it using the blueprint:

resources/user.py
from flask.views import MethodView
from flask_smorest import Blueprint, abort
from passlib.hash import pbkdf2_sha256

from db import db
from models import UserModel
from schemas import UserSchema


blp = Blueprint("Users", "users", description="Operations on users")


@blp.route("/register")
class UserRegister(MethodView):
@blp.arguments(UserSchema)
def post(self, user_data):
if UserModel.query.filter(UserModel.username == user_data["username"]).first():
abort(409, message="A user with that username already exists.")

user = UserModel(
username=user_data["username"],
password=pbkdf2_sha256.hash(user_data["password"]),
)
db.session.add(user)
db.session.commit()

return {"message": "User created successfully."}, 201

Creating a testing-only User resource

Let's also create a User resource that we will only use during testing. It allows us to retrieve information about a single user, or delete a user. This will be handy so that using Insomnia or Postman we can clear the registered users and we don't have to change our request arguments each time!

resources/user.py
@blp.route("/user/<int:user_id>")
class User(MethodView):
"""
This resource can be useful when testing our Flask app.
We may not want to expose it to public users, but for the
sake of demonstration in this course, it can be useful
when we are manipulating data regarding the users.
"""

@blp.response(200, UserSchema)
def get(self, user_id):
user = UserModel.query.get_or_404(user_id)
return user

def delete(self, user_id):
user = UserModel.query.get_or_404(user_id)
db.session.delete(user)
db.session.commit()
return {"message": "User deleted."}, 200

Register the user blueprint in app.py

Finally, let's go to app.py and register the blueprint!

app.py
+from resources.user import blp as UserBlueprint
from resources.item import blp as ItemBlueprint
from resources.store import blp as StoreBlueprint
from resources.tag import blp as TagBlueprint

...

+api.register_blueprint(UserBlueprint)
api.register_blueprint(ItemBlueprint)
api.register_blueprint(StoreBlueprint)
api.register_blueprint(TagBlueprint)