14 : Our First FastAPI Route !


Time for our first real API route. Till now we have made very simple routes, This time we will be using pydantic schemas, database connections, dependencies all at one endpoint. We are going to make a route which will enable creation of users. Why are we doing this first? Its because in our 'Job' model, we have a foreign key to the users table. So, we need an owner_id which is basically id of an user model. Lets jump into the code but before that create this new folder structure:

│ ├─base.py                   #new file
│ └─version1/                 #new folder
│   ├─route_general_pages.py    #new
│   └─route_users.py            #new
│ ├─config.py
│ └─hashing.py
│ ├─base.py
│ ├─base_class.py
│ ├─models/
│ │ ├─jobs.py
│ │ └─users.py
│ ├─repository/                 #new
│ │ └─users.py                  #new
│ └─session.py
│ ├─jobs.py
│ └─users.py

Copy everything from general_pages > route_homepage.py to version1 > route_general_pages.py
Now, we need to type the below lines in apis > version1 > route_users.py

from fastapi import APIRouter
from sqlalchemy.orm import Session
from fastapi import Depends

from schemas.users import UserCreate
from db.session import get_db
from db.repository.users import create_new_user

router = APIRouter()

def create_user(user : UserCreate,db: Session = Depends(get_db)):
    user = create_new_user(user=user,db=db)
    return user 

Type the following in db > repository > users.py

from sqlalchemy.orm import Session

from schemas.users import UserCreate
from db.models.users import User
from core.hashing import Hasher

def create_new_user(user:UserCreate,db:Session):
    user = User(username=user.username,
        email = user.email,
    return user
  1. Now we need to include the router in route_users.py file to our app in main.py file. But think of it, if we have 100 routers, should we import and include 100 routes in main.py file? No, it will get cluttered, so, I am going to make a new router in apis > base.py file which will contain the information of other routers. Put the following code in apis > base.py
from fastapi import APIRouter

from apis.version1 import route_general_pages
from apis.version1 import route_users

api_router = APIRouter()

Just one step more, make sure we import this 'api_router' in main.py file and include with our app: main.py

from core.config import settings
from apis.base import api_router #new
from db.session import engine
from db.base import Base 

def include_router(app):   
	app.include_router(api_router) #modified


All done. Let's verify its working:

But there is a problem with this approach, Just look at all the data we are showing to our users. 

  "hashed_password": "$2b$12$qsPsF3.JVAwWYqsioLvuJOOSiJCZuWRv5yCBCuFdumoA1bYRlXhCO",
  "email": "some2@example.com",
  "is_superuser": false,
  "username": "someonez",
  "id": 3,
  "is_active": true

We are passing hashed_password, id, and is_superuser status, These are implementation details and from a security point of view, we should not pass these data. Let's restrict our response to only username, email and is_active status. Remember pydantic schemas? They are used to validate request data. Similarly, they can be used to restrict data to have only a limited number of fields.
Let's add a new schema in schemas > users.py

from typing import Optional
from pydantic import BaseModel,EmailStr

#properties required during user creation
class UserCreate(BaseModel):
    username: str
    email : EmailStr
    password : str

class ShowUser(BaseModel):   #new
    username : str 
    email : EmailStr
    is_active : bool

    class Config():  #tells pydantic to convert even non dict obj to json
        orm_mode = True

and we need to specify this ShowUser schemas as a response_model of our post route. I believe it would be better to call it request_schema!!  Ok, now we modify our apis > version1 > route_users.py as follows:


from schemas.users import UserCreate,ShowUser  #modified
from db.session import get_db

router = APIRouter()

@router.post("/",response_model = ShowUser)          #modified
def create_user(user : UserCreate,db: Session = Depends(get_db)):
    user = create_new_user(user=user,db=db)
    return user 

All done, now we are not passing hashed_password, id, etc. 

Final git commit :support user creation using post · nofoobar/JobBoard-Fastapi@48c601d (github.com)

Prev: 13 : Password … Next: 15 : Unit …

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.



Refund Policy

Follow us on our social media channels to stay updated.

© Copyright 2022-23 Team FastAPITutorial