This article discusses extending a FastAPI application to implement user registration functionality, including endpoint creation, data validation, and response modeling.
In this article, we extend our previous implementation for posts by adding a new path operation to create a user. While the process is similar to creating a post, there are key modifications needed to handle user-specific details like email and password.Below is the original posts creation endpoint for reference:
app/models.py", "C:\Users\sanje\Documents\Courses\fastapi\app\models.py.915f4585d116cbddab21f73e5527481.tmp": Reloading...Database connection was successfullINFO: Started server process [27704]INFO: Waiting for application startup.INFO: Application startup complete.
Later in the article, we update an existing post. The following snippet retrieves a post by its ID, raises an exception if it’s not found, applies updates using new data, commits the changes, and returns the updated post:
Copy
Ask AI
post_query = db.query(models.Post).filter(models.Post.id == id)post = post_query.first()if post is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"post with id: {id} does not exist")post_query.update(updated_post.dict(), synchronize_session=False)db.commit()return post_query.first()
Copy
Ask AI
INFO: Started server process [27704]INFO: Waiting for application startup.INFO: Application startup complete.
To create a new user, modify the decorator to target the /users URL. In this refactoring, we switch from handling posts to managing user registration. For simplicity, we temporarily remove the response model.Below is the refactored endpoint for user creation:
WARNING: WatchGodReload detected file change in '['C:\\Users\\sanje\\Documents\\Courses\\fastapi\\app\\main.py.dbfc928ea7d1f64e03ca5f2a29d1b.tmp']: Reloading...INFO: Database connection was successful!INFO: Started server process [2520]INFO: Waiting for application startup.INFO: Application startup complete.
The function create_user clearly aligns with the endpoint’s purpose. Remember that when creating any resource, the default status code should be 201.
When receiving registration data, the incoming JSON must include both an email and a password. We create a dedicated Pydantic schema to enforce required fields. Below are the model definitions for posts and the initial user creation schema:
Copy
Ask AI
class PostCreate(PostBase): passclass Post(PostBase): id: int created_at: str class Config: orm_mode = Trueclass UserCreate: email: str password: str
For additional validation of email addresses, we use Pydantic’s EmailStr. This ensures that the provided email follows a valid format. Make sure the email-validator library is installed (it comes automatically when installing FastAPI with the all flag, or you can install it via pip install email-validator).Below is an updated version that uses EmailStr and improves date handling for posts:
Back in the main application file, define the endpoint to create a new user by adapting the logic from the post creation operation. Notice how we convert the incoming Pydantic object to a dictionary and unpack it when instantiating the SQLAlchemy model, which facilitates proper insertion.The following snippet demonstrates the user creation endpoint:
Again, observe the console messages as the server reloads and confirms the database connection:
Copy
Ask AI
WARNING: WatchGodReload detected file change in '['C:\\Users\\sanje\\Documents\\Courses\\fastapi\\app\\main.py.dfbc928ea7d1f64e03ca5f2a29d1b.tmp']: Reloading...INFO: Database connection was successful!INFO: Started server process [2520]INFO: Waiting for application startup.INFO: Application startup complete.
Use an API client like Postman to test the endpoint. Create a new POST request named “create user” and set the request body to raw JSON. For example, use the following payload:
Ensure that the URL points to /users instead of /posts. When the request is sent, you should receive a response containing the user’s email, creation timestamp, and ID. For instance:
To ensure the email validator is working, try submitting a request with an invalid email format. In this case, the schema validator returns an error message similar to:
Copy
Ask AI
{ "detail": [ { "loc": [ "body", "email" ], "msg": "value is not a valid email address", "type": "value_error.email" } ]}
After correcting the email—for example, using “[email protected]”—the endpoint successfully creates and returns the user.
To prevent sensitive information (like the password) from being returned in the API response, define a new Pydantic model called UserOut. This model includes the user ID, email, and optionally the creation timestamp.
Copy
Ask AI
class UserOut(BaseModel): id: int email: EmailStr class Config: orm_mode = True
Now, update your user creation endpoint to use the UserOut response model:
To include all desired fields (such as created_at), ensure that your models are updated accordingly:
Copy
Ask AI
class PostCreate(PostBase): passclass Post(PostBase): id: int created_at: datetime class Config: orm_mode = Trueclass UserCreate(BaseModel): email: EmailStr password: strclass UserOut(BaseModel): id: int email: EmailStr class Config: orm_mode = True
This configuration guarantees that the response model accurately represents the stored data without exposing sensitive details like the password. With these improvements, your API now securely processes user registration by enforcing email validation, handling user data safely, and returning only the necessary information to the client.