User Registration in FastAPI webapp

Git Commit: user registration in webapp
Well, that was pretty good, Now, our users will see the details of a blog post. But what if someone wants to create a blog post? Do you remember, each blog post should have an author? That means we need to provide our users with a way to register and log in. In this post, we are going to see the signup/registration part. Let's put our code for user registration in a new file apps > v1 > route_login.py

import json
from fastapi import APIRouter, Request, Depends
from fastapi.templating import Jinja2Templates
from fastapi import responses, status, Form
from sqlalchemy.orm import Session

from db.session import get_db
from schemas.user import UserCreate
from db.repository.user import create_new_user
from pydantic.error_wrappers import ValidationError

templates = Jinja2Templates(directory="templates")
router = APIRouter()

@router.get("/register")
def register(request: Request):
    return templates.TemplateResponse("auth/register.html",{"request":request})

@router.post("/register")
def register(request: Request, email: str = Form(...), password: str= Form(...), db: Session = Depends(get_db)):
    errors = []
    try:
        user = UserCreate(email=email,password=password)
        create_new_user(user=user, db=db)
        return responses.RedirectResponse("/?alert=Successfully%20Registered",status_code=status.HTTP_302_FOUND)
    except ValidationError as e:
        errors_list = json.loads(e.json())
        for item in errors_list:
            errors.append(item.get("loc")[0]+ ": " + item.get("msg"))
        return templates.TemplateResponse("auth/register.html",{"request":request,"errors":errors})
    

Let's understand what's happening:

  • Our users will visit a link e.g. http://127.0.0.1:8000/auth/register/ and they should see a form with an email and password field.
  • After we fill up the form, we would click on the submit button and will make a post request that will contain the details entered by the users.
  • Why post a request? Because if they submit the form with the get request all the details even the password would be appended to the URL and this makes it extremely insecure.
  • When the post request would come we extract the email and password from the form data and create a user.

Moving on to the next section, We need to tell our fastapi app that we have made this functionality. So, its time to modify apps > base.py

from apps.v1 import route_blog
from apps.v1 import route_login
from fastapi import APIRouter

app_router = APIRouter()

#new
app_router.include_router(
    route_login.router, prefix="/auth", tags=[""], include_in_schema=False
)

The final touch, We need to make an HTML form which should display a form as well as should display the errors in the form. Plus, any data which the user fills in should be there if the form has an error. That's why we have value = {{username}} kind of thing. Let's create a template at templates > auth > register.html

{% extends "base.html" %}

{% block title %}
<title>Sign Up</title>
{% endblock %}


{% block content %}

{% for error in errors %}
<div class="alert alert-danger">
    <li>{{error}}</li>
</div>
{% endfor %}

<div class="container">
    <div class="text-center display-4">Register</div>
    <div class="row mt-3 mb-5">
        <div class="col-3"></div>
        <div class="col-6">
            <form method="POST">
                <label>Email</label>
                <input type="email" required  class="form-control mb-2" name="email" value="{{email}}" placeholder="Enter your email">
    
                <label>Password</label>
                <input type="password" required placeholder="Choose a secure password" value="{{password}}" name="password" class="form-control mb-2">
    
                <button type="submit" class="btn btn-outline-success">Create an Account</button>
            </form>
        </div>
        <div class="col-3"></div>
    </div>
</div>

{% endblock %}

Woahhh!  That was a lot of work. One last thing, promise this is last 😁
if everything works correctly, We might want to redirect the user to the homepage and show an alert message that should say "Successfully Registered". To implement this, we need to an optional query parameter to our homepage route. (apps > v1 > route_blog.py)

@router.get("/")
def home(request: Request,alert: Optional[str] = None, db: Session = Depends(get_db)):
    blogs = list_blogs(db=db)
    return templates.TemplateResponse(
        "blog/home.html", {"request": request, "blogs": blogs,"alert":alert}
    )

Obviously, since, it is now passing an alert message to the frontend, we will need to catch the alert message and display it as an alert.

{% extends "base.html" %}


{% block title %}
<title>Algoholic</title>
{% endblock %}


{% block content %}
{% with alert=alert %}    
    {% include "components/alert.html" %}
{% endwith %}

<!-- Old content here -->

{% endblock %}

Finally, one last thing, we would need to implement templates > components > alert.html

{% if alert %}
  <div class="alert alert-info" role="alert">
    {{alert}}
  </div>
{% endif %}


Time to test our work now. visit http://127.0.0.1:8000/auth/register/ and you should see the form and it should be working properly. There is a huge scope for improvement, especially in this code, We should have done much more validation in the implementation of the form, which I am leaving up to you. We should have also checked if a user with the same email already exists. If the same email exists, Our system will raise a validation error. As an assignment, I leave it up to you to catch the exception and show a proper message. Also, we have not passed the email and password, in case an error occurs. It makes it irritating for the end users to fill in the same information all again.

FastAPITutorial

Brige the gap between Tutorial hell and Industry. We want to bring in the culture of Clean Code, Test Driven Development.

We know, we might make it hard for you but definitely worth the efforts.

Contacts

Refunds:

Refund Policy
Social

Follow us on our social media channels to stay updated.

© Copyright 2022-23 Team FastAPITutorial