Skip to main content
In this article, you will learn how to create a new post using SQLAlchemy—the powerful Python ORM that abstracts raw SQL commands into clean, maintainable code. This guide demonstrates how to migrate from raw SQL queries to a more standardized approach using FastAPI and SQLAlchemy.

Initial Implementation with Raw SQL

Below is an initial implementation that uses raw SQL commands to create a new post:
During execution, you might observe errors and system logs similar to the following:

Transitioning to SQLAlchemy ORM

SQLAlchemy provides an abstraction layer that eliminates the need to write direct SQL queries. Instead, you can leverage ORM models to handle database operations smoothly. When working with FastAPI, it is important to include the database dependency in your path operations, which simplifies unit testing and centralizes database management through dependency injection. Below is an updated example using FastAPI’s Depends to pass the database session:
You might notice similar log messages when running this code:

Defining the ORM Model

For the ORM approach, define models that represent your database tables. The example below shows how the Post model is structured:
When working with FastAPI, import and initialize your models as follows:
After importing, you can access the model using models.Post.

Creating a New Post Using SQLAlchemy

To create a new post, populate the SQLAlchemy model with attributes (title, content, published) provided by the request object. The following updated endpoint demonstrates how to create a new post using ORM:
Once the post is saved, sending a request with the following JSON payload:
may result in a response like:
And your server logs might display messages similar to:
However, if you query your PostgreSQL database with:
and do not see the newly created post, it indicates that changes were not properly committed. With SQLAlchemy, remember to add the new post to the session, commit the transaction, and refresh the instance to retrieve auto-generated fields such as id and created_at. The corrected handler is shown below:

Simplifying with Dictionary Unpacking

Manually mapping each attribute from the Pydantic model to the SQLAlchemy model can be tedious as the number of fields increases. Since post is an instance of a Pydantic model, you can convert it to a dictionary using post.dict(). By leveraging Python’s dictionary unpacking, you can simplify the creation of the ORM model instance:
Using **post.dict() automatically unpacks the dictionary into keyword arguments that match the fields defined in your Post model. This method is scalable and easier to maintain when additional fields are introduced.
Check that your model is defined accurately. The fields in your Pydantic model should directly correspond to the fields in your SQLAlchemy model for seamless data mapping.

Final Endpoint Implementation

After consolidating the improvements, your cleaner and final endpoint implementation is as follows:
This approach eliminates the need for manual attribute mapping, ensures that all changes are correctly committed to PostgreSQL, and makes your codebase more scalable and maintainable.
Remember to always commit your database session after adding new entries. Missing a commit could result in data not being persisted in the database.

Watch Video