Skip to content
OVEX TECH
Education & E-Learning

Organize FastAPI Routes with APIRouter Modules

Organize FastAPI Routes with APIRouter Modules

How to Organize FastAPI Routes with APIRouter Modules

As your FastAPI application grows, managing all your routes in a single file can quickly become overwhelming. This tutorial will guide you through organizing your FastAPI project by leveraging APIRouter to group related routes into separate modules. This approach enhances maintainability, scalability, and collaboration, making your codebase cleaner and easier to navigate. We’ll refactor an existing application to demonstrate how to create and include routers, apply prefixes, and utilize tags for improved documentation.

What You’ll Learn

  • How to create a modular structure for your FastAPI application using APIRouter.
  • The process of moving existing routes from your main application file into dedicated router files.
  • How to include routers in your main application with custom URL prefixes.
  • The benefits of using tags for organizing API documentation.
  • Best practices for maintaining a clean and scalable FastAPI project.

Prerequisites

  • A working FastAPI application with existing routes (preferably following previous tutorials in this series, covering CRUD operations and async/await).
  • Basic understanding of Python and FastAPI concepts.
  • An IDE or text editor for coding.
  • A terminal or command prompt for running the server.

Step 1: Create the Routers Directory

First, we need a dedicated place to store our route modules. In your project’s root directory, create a new folder named routers. Inside this folder, create an empty file named __init__.py. This file signifies that the routers directory should be treated as a Python package, which is a good practice for organizing modules.

  1. Navigate to your project’s root directory in your terminal.
  2. Create the directory: mkdir routers
  3. Change into the new directory: cd routers
  4. Create the initialization file: touch __init__.py (or create it manually in your file explorer).
  5. Navigate back to your project’s root directory.

Step 2: Create Router Files for Users and Posts

Now, let’s create separate Python files within the routers directory for our user and post routes. These files will contain the logic and route definitions specific to each resource.

  1. Inside the routers directory, create a new file named users.py.
  2. Inside the routers directory, create another new file named post.py.

Step 3: Move User Routes to users.py

We’ll start by moving the API routes related to users from your main application file (e.g., main.py) into the newly created users.py file. Remember to adjust the imports and route decorators accordingly.

  1. Open users.py in your editor.
  2. Add the necessary imports. This will include API_router from fastapi, your database dependencies, Pydantic models, and schemas that are specific to user operations.
  3. Instantiate an APIRouter: router = APIRouter().
  4. Identify all API routes in main.py that start with the path /api/users. These are typically your CRUD operations for users.
  5. Cut these routes from main.py and paste them into users.py.
  6. For each route moved, change the decorator from app.get, app.post, etc., to router.get, router.post, etc.
  7. Modify the path for each route. Instead of the full path like /api/users or /api/users/{user_id}, use a relative path. For the base user routes, you can use an empty string ("") or a single forward slash ("/"). For specific user IDs, use "/{{user_id}}". The full prefix will be applied when we include this router in main.py.
  8. Example for a route: If you had @app.post("/api/users/"), it becomes @router.post("") in users.py.
  9. Ensure all necessary dependencies and logic remain intact.

Expert Note: Using an empty string for the base path in the router (e.g., @router.post("")) combined with a prefix like /api/users when including the router results in the final URL /api/users. This avoids issues with trailing slashes and potential redirects.

Step 4: Move Post Routes to post.py

Follow a similar process to move the API routes related to posts into the post.py file.

  1. Open post.py in your editor.
  2. Add the necessary imports, including API_router, database dependencies, models, and schemas relevant to posts.
  3. Instantiate an APIRouter: router = APIRouter().
  4. Identify all API routes in main.py that start with the path /api/posts.
  5. Cut these routes from main.py and paste them into post.py.
  6. For each route, change the decorator from app.xxx to router.xxx.
  7. Adjust the path to be relative. Use an empty string ("") for the base post routes and paths like "/{{post_id}}" for specific post operations.
  8. Ensure all dependencies and logic are correctly transferred.

Step 5: Update main.py to Include Routers

Now, we need to modify our main application file to import and include the routers we’ve created. This step consolidates the application setup while keeping the route definitions separate.

  1. Open your main application file (e.g., main.py).
  2. Clean up imports: Remove any imports for Pydantic schemas, models, or database dependencies that are now exclusively used within your router files.
  3. Add new imports to bring in your routers: from routers import users, post.
  4. Locate where you initialize your FastAPI app (e.g., app = FastAPI()).
  5. After setting up your app, static mounts, and templates, add calls to app.include_router() for each of your new routers.
  6. When including a router, specify a prefix and optionally tags. The prefix will be prepended to all routes defined within that router. Tags help organize the OpenAPI documentation.
  7. Example for users router:
    app.include_router(users.router, prefix="/api/users", tags=["users"])
  8. Example for posts router:
    app.include_router(post.router, prefix="/api/posts", tags=["posts"])
  9. Review your main.py. It should now be significantly shorter, primarily containing app configuration, lifespan events, template setup, router inclusions, and any remaining template routes or exception handlers.

Tip: The tags parameter is crucial for organizing the automatically generated API documentation (Swagger UI/ReDoc). It groups related endpoints under collapsible headers, making it much easier for developers to understand and use your API.

Warning: Be mindful of function naming conflicts. If you have a function named home in a router and also a template route named home in main.py, FastAPI might encounter issues. Ensure function names within routers are unique or descriptive enough to avoid collisions with routes defined directly in main.py.

Step 6: Verify Functionality and Documentation

With the restructuring complete, it’s time to ensure everything still works as expected and to observe the benefits of the new organization.

  1. Save all your modified files.
  2. Run your FastAPI application using your preferred method (e.g., uvicorn main:app --reload).
  3. Open your browser and navigate to your application’s homepage and other template routes to confirm they are still accessible.
  4. Access your API endpoints directly (e.g., using tools like Postman or `curl`) to verify that their functionality remains unchanged.
  5. Navigate to your API documentation (e.g., /docs or /redoc). You should now see your API endpoints neatly organized into sections based on the tags you provided (e.g., ‘users’ and ‘posts’).
  6. Test key API operations, such as creating a user and then creating a post associated with that user, to ensure data integrity and correct responses.

Benefits of Using APIRouter

By organizing your FastAPI application with APIRouter, you gain several significant advantages:

  • Separation of Concerns: Logic related to specific resources (like users or posts) is kept together, making the codebase more modular and understandable.
  • Improved Maintainability: Smaller, focused files are easier to read, debug, and modify than a single monolithic file.
  • Scalability: As your application grows, you can easily add new features by creating new router files without cluttering your main application file.
  • Team Collaboration: Different developers can work on different routers simultaneously with fewer merge conflicts.
  • Better Documentation Organization: Tags provide a clear structure to your API documentation, enhancing usability.
  • Reusability: Routers can potentially be reused across different parts of a larger application or even in other projects.

This modular approach is a fundamental pattern for building robust and scalable web applications with FastAPI.


Source: Python FastAPI Tutorial (Part 8): Routers – Organizing Routes into Modules with APIRouter (YouTube)

Leave a Reply

Your email address will not be published. Required fields are marked *

Written by

John Digweed

1,284 articles

Life-long learner.