Prisma with Python and FastAPI

Hyo
dooboolab
Published in
4 min readJun 19, 2022

Brief experience on Prisma with Python and FastApi.

We’ve been using Prisma quite a lot for many years and it made our developer experience really enjoyable and capable.

We’ve worked on a few boilerplates and toy projects with Prisma like HackaTalk, Apollo Prisma Boilerplate, Fastify Prisma Boilerplate, and so on. Other than that, we also use Prisma in our production projects like Puzz.

Today, we’ve been working on few AI projects using Python and recently we were thinking about how to serve our AI apis. Firstly, we thought of using nodejs but then our AI developers should learn new language since most of them are much familiar with Python.

We found FastAPI written in Python which serves great performance as a server programming. Therefore, we decided to use it.

Then how about Prisma?

While finding which ORM to use to connect to the database, we decided to try Prisma Python Client, which has been developed by the community.

Introducing Robert Craigie, the author of Prisma Python Client

There is also a discussion on the Prisma python client on the official repository.

Let’s create a boilerplate from scratch!

1. Install Prisma Client

Create `schema.prisma` like we did in nodejs project.

If you see schema.prisma file, the only difference is the client generator.

You can read more in document

Install package and run prisma generate.

pip install prismaprisma generate

Create src/prisma.py and paste the below code.

from prisma import Prismaprisma = Prisma()

2. Install FastAPI

Create main.py

from src.apis import apis
from src.prisma import prisma
from fastapi.middleware.gzip import GZipMiddleware
from fastapi import FastAPI
app = FastAPI()
app.add_middleware(GZipMiddleware, minimum_size=1000)
app.include_router(apis, prefix="/apis")
@app.on_event("startup")
async def startup():
await prisma.connect()
@app.on_event("shutdown")
async def shutdown():
await prisma.disconnect()
@app.get("/")
def read_root():
return {"version": "1.0.0"}

Create routers in src/apis. As shown below, we created __init__.py and auth.py.

  • __init__.py
from fastapi import APIRouterfrom src.apis.auth import router as authRouterapis = APIRouter()
apis.include_router(authRouter)
__all__ = ["apis"]
  • auth.py
import datetime
from typing import List, Optional
from fastapi import APIRouter
from prisma.models import User
from pydantic import BaseModel
from src.models.scalar import Gender
from src.prisma import prisma
from src.utils.auth import (
encryptPassword,
signJWT,
validatePassword,
)
router = APIRouter()class SignIn(BaseModel):
email: str
password: str
class SignInOut(BaseModel):
token: str
user: User
@router.post("/auth/sign-in", tags=["auth"])
async def sign_in(signIn: SignIn):
user = await prisma.user.find_first(
where={
"email": signIn.email,
}
)
validated = validatePassword(signIn.password, user.password)
del user.password
if validated:
token = signJWT(user.id)
return SignInOut(token=token, user=user)
return Noneclass SignUp(BaseModel):
email: str
password: str
name: Optional[str] = None
nickname: Optional[str] = None
birthday: Optional[datetime.date] = None
gender: Optional[Gender] = None
phone: Optional[str] = None
@router.post("/auth/sign-up", tags=["auth"])
async def sign_up(user: SignUp):
password = encryptPassword(user.password)
created = await prisma.user.create(
{
"email": user.email,
"password": encryptPassword(user.password),
"name": user.name,
"nickname": user.nickname,
"birthDay": user.birthday,
"gender": user.gender,
"phone": user.phone,
}
)
return created

We created simple signUp and signIn apis. With rest client, we can see that the APIs are working as expected.

Note: You can get client model class from prisma.models and import models like User which is defined in schema.prisma.

If you want to try the above, you can come and take a look at our Prisma FastAPI boilerplate and test it out. Feel free to give any arguments related to this.

Thanks for reading 🙏. If you want to add graphql over this, you may follow up in the next post.

--

--