FastAPI is a Python web framework specially for building APIs. In this article, we will be looking into PostgreSQL with Django.
PostgreSQL is an object-relational database that uses and extends the SQL language to scale and store big complicated data in the database.
The example below demonstrates how PostgreSQL can be used alongside FastAPI.
Installation:
pip install pipenv
pipenv shell
pipenv install fastapi fastapi-sqlalchemy pydantic alembic psycopg2 uvicorn python-dotenv
Create a file and name it models.py
. This file is responsible for creating the model for the database.
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String, Float from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship from sqlalchemy.sql import func Base = declarative_base() class Book(Base): __tablename__ = 'book' id = Column(Integer, primary_key=True, index=True) title = Column(String) rating = Column(Float) time_created = Column(DateTime(timezone=True), server_default=func.now()) time_updated = Column(DateTime(timezone=True), onupdate=func.now()) author_id = Column(Integer, ForeignKey('author.id')) author = relationship('Author') class Author(Base): __tablename__ = 'author' id = Column(Integer, primary_key=True) name = Column(String) age = Column(Integer) time_created = Column(DateTime(timezone=True), server_default=func.now()) time_updated = Column(DateTime(timezone=True), onupdate=func.now())
Create another file and name it schema.py
. It is used to write how an object in a model can be easily mapped using ORM
# build a schema using pydantic from pydantic import BaseModel class Book(BaseModel): title: str rating: int author_id: int class Config: orm_mode = True class Author(BaseModel): name:str age:int class Config: orm_mode = True
Create a file and name it main.py
. This file is used to create functions or classes that visualize how a route will operate.
import uvicorn from fastapi import FastAPI from fastapi_sqlalchemy import DBSessionMiddleware, db from schema import Book as SchemaBook from schema import Author as SchemaAuthor from schema import Book from schema import Author from models import Book as ModelBook from models import Author as ModelAuthor import os from dotenv import load_dotenv load_dotenv('.env') app = FastAPI() # to avoid csrftokenError app.add_middleware(DBSessionMiddleware, db_url=os.environ['DATABASE_URL']) @app.get("/") async def root(): return {"message": "hello world"} @app.post('/book/', response_model=SchemaBook) async def book(book: SchemaBook): db_book = ModelBook(title=book.title, rating=book.rating, author_id = book.author_id) db.session.add(db_book) db.session.commit() return db_book @app.get('/book/') async def book(): book = db.session.query(ModelBook).all() return book @app.post('/author/', response_model=SchemaAuthor) async def author(author:SchemaAuthor): db_author = ModelAuthor(name=author.name, age=author.age) db.session.add(db_author) db.session.commit() return db_author @app.get('/author/') async def author(): author = db.session.query(ModelAuthor).all() return author # To run locally if __name__ == '__main__': uvicorn.run(app, host='0.0.0.0', port=8000)
.env
..env
file, do the following:
DATABASE_URI = 'postgresql://postgres:<password>@localhost/<name_of_the_datbase>'
Here, we will add a link to our PostgreSQL database.
After it, run this command:
alembic init alembic
It will create a folder called alembic
. Inside the folder, go to the env.py
file and do the following:
from logging.config import fileConfig from sqlalchemy import engine_from_config from sqlalchemy import pool from alembic import context # My code import os,sys from dotenv import load_dotenv BASE_DIR= os.path.dirname(os.path.dirname(os.path.abspath(__file__))) load_dotenv(os.path.join(BASE_DIR, '.env')) sys.path.append(BASE_DIR) # This is the Alembic Config object, which provides # Access to the values within the .ini file in use. config = context.config # Making a connection config.set_main_option('sqlalchemy.url', os.environ['DATABASE_URL']) # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) import models # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata target_metadata = models.Base.metadata # other values from the config, defined by the needs of env.py, # can be acquired: # my_important_option = config.get_main_option("my_important_option") # ... etc. def run_migrations_offline(): """Run migrations in 'offline' mode. This configures the context with just a URL and not an Engine, though an Engine is acceptable here as well. By skipping the Engine creation we don't even need a DBAPI to be available. Calls to context.execute() here emit the given string to the script output. """ url = config.get_main_option("sqlalchemy.url") context.configure( url=url, target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"}, ) with context.begin_transaction(): context.run_migrations() def run_migrations_online(): """Run migrations in 'online' mode. In this scenario we need to create an Engine and associate a connection with the context. """ connectable = engine_from_config( config.get_section(config.config_ini_section), prefix="sqlalchemy.", poolclass=pool.NullPool, ) with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata ) with context.begin_transaction(): context.run_migrations() if context.is_offline_mode(): run_migrations_offline() else: run_migrations_online()
RELATED TAGS
CONTRIBUTOR
View all Courses