Git Commit: post request to create blog
Now, we have a record in the user table so we have the author_id field for creating a new blog. Let's create a new blog using a post request. It would be very similar to the previous post, Wanna give it a try? Feel free to try it on your own.
We need 3 new files:
backend/
├─.env
├─alembic/
├─apis/
│ ├─base.py
│ └─v1/
│ └─route_user.py
│ └─route_blog.py #new file
├─core/
├─db/
│ ├─repository/
│ │ └─user.py
│ │ └─blog.py #new file
├─requirements.txt
├─schemas/
│ ├─blog.py #new file
Type the following code in route_blog.py:
from fastapi import APIRouter, status
from sqlalchemy.orm import Session
from fastapi import Depends
from db.session import get_db
from schemas.blog import ShowBlog, CreateBlog
from db.repository.blog import create_new_blog
router = APIRouter()
@router.post("/blogs",response_model=ShowBlog, status_code=status.HTTP_201_CREATED)
async def create_blog(blog: CreateBlog, db: Session= Depends(get_db)):
blog = create_new_blog(blog=blog,db=db,author_id=1)
return blog
We are doing the same thing, we are creating a route that will receive data for blog creation by POST method. It will validate the data received using a schema named CreateBlog. The only catch is that we will not be asking for the slug from the users, rather we will build it from the title provided. Since we want to do the slug generation even before the request body data is validated by Pydantic, we will have to put the pre=True keyword in our validator. So, let's create the schemas required. Type the following in schemas > blog.py.
from typing import Optional
from pydantic import BaseModel, root_validator
from datetime import date
class CreateBlog(BaseModel):
title: str
slug: str
content: Optional[str] = None
@root_validator(pre=True)
def generate_slug(cls, values):
if 'title' in values:
values['slug'] = values.get("title").replace(" ","-").lower()
return values
class ShowBlog(BaseModel):
title:str
content: Optional[str]
created_at: date
class Config():
orm_mode = True
Since we are using a repository pattern and we want to keep the database orm logic completely separated from that of fastapi routes we need to create a make a new function named 'create_new_blog' for creation logic. Let's create this file db > repository > blog.py
from sqlalchemy.orm import Session
from schemas.blog import CreateBlog
from db.models.blog import Blog
def create_new_blog(blog: CreateBlog, db: Session, author_id:int = 1):
blog = Blog(**blog.dict(),author_id=author_id)
db.add(blog)
db.commit()
db.refresh(blog)
return blog
This is yet another example of sqlalchemy orm. We are creating a new record in the database using orm. Still, our fastapi app does not know about this new feature. So, we need to import create_blog route in apis > base.py
from fastapi import APIRouter
from apis.v1 import route_user,route_blog
api_router = APIRouter()
api_router.include_router(route_user.router,prefix="",tags=["users"])
api_router.include_router(route_blog.router,prefix="",tags=["blogs"])
All Done, over and out!
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.
© Copyright 2022-23 Team FastAPITutorial