Search code examples
pythonmoduleprojectnaming-conventionsdirectory-structure

FastAPI project naming conventions/structure


I have the following structure (relevant portion) for a small API:

app
 |--main.py
 |-models
   |--base.py
   |--ModelUser.py
   |--ModelCompany.py
   |--ModelUser.py
 |-schemas
   |--SchemaUser.py
   |--SchemaCompany.py
   |--SchemaReview.py
 |-routes
   |--auth_router.py
   |--companies_router.py
   |_users_router.py
 |-utils
   |--crud_company.py
   |--crud_review.py
   |--crud_user.py

For the most part, it works and keeps an acceptable degree of separation of concerns (ie., UserModel contains the SQLAlchemy User model, SchemaCompany contains the Pydantic Company model, etc.). Thing is, the namespace has become a little too cluttered and redundant, as each class or function call requires me to type, for example, SchemaReview.Review or ModelUser.User or crud_company.get_companies (you get the idea).

I'd much rather have something like model.User, schema.Company and crud.get_reviews, but in order to achieve this I would have to put every model in a single model.py file, every schema in a single schema.py file, etc., which is exactly what I'm trying to avoid by modularizing the code.

So, what would the best approach here? I've thought of aliasing the imports, but that may lead to inconsistencies along the way, which I'd rather not get into. So I think the ideal approach would come from a directory/filename convention, that will force me to maintain coherence.

All ideas wellcome. Thanks!


Solution

  • Have a look into the FastAPI's creator template for FastAPI-Postgres App.

    I've seen the convention of never naming python files in PascalCase and use snake_case exclusively.

    The way you can achieve model.User is to import relevant classes in __init__.py of relevant file.

    Let's say models.__init__.py

    from .ModelUser import User
    from .ModelCompany import Company
    from .ModelReview import ModelReview
    

    Then you can import models and have models.User used throughout the code. This might create naming conflicts if you use PascalCase for file names, so that's also why snake_case is more practical.

    FYI, you can also post questions on the FastAPI discussions board.