@@ -6,38 +6,48 @@ description: End-to-end ArchiPy application — entities, DTOs, adapters, reposi
66# Complete User Example
77
88This page walks through every layer of a real ArchiPy application for a ** User** domain, from the database
9- entity all the way to the FastAPI endpoint and ` main .py` . Each section corresponds to one layer in the
9+ entity all the way to the FastAPI endpoint and ` manage .py` . Each section corresponds to one layer in the
1010[ four-layer architecture] ( ../getting-started/concepts.md ) .
1111
1212---
1313
1414## Project Layout
1515
1616```
17- my_app/
18- ├── configs/
19- │ ├── app_config.py
20- │ └── containers.py
21- ├── models/
22- │ ├── dtos/
17+ project-root/
18+ ├── my_app/
19+ │ ├── configs/
20+ │ │ ├── app_config.py
21+ │ │ └── containers.py
22+ │ ├── models/
23+ │ │ ├── dtos/
24+ │ │ │ └── user/
25+ │ │ │ ├── domain/v1/user_dtos.py # versioned — cross service boundary
26+ │ │ │ └── repository/user_dtos.py # internal — never versioned
27+ │ │ ├── entities/user.py
28+ │ │ └── errors/user_errors.py
29+ │ ├── repositories/
2330│ │ └── user/
24- │ │ ├── domain/v1/user_dtos.py # versioned — cross service boundary
25- │ │ └── repository/user_dtos.py # internal — never versioned
26- │ ├── entities/user.py
27- │ └── errors/user_errors.py
28- ├── repositories/
29- │ └── user/
30- │ ├── adapters/
31- │ │ ├── user_db_adapter.py
32- │ │ └── user_cache_adapter.py
33- │ └── user_repository.py
34- ├── logics/
35- │ └── user/
36- │ ├── user_registration_logic.py
37- │ └── user_query_logic.py
38- ├── services/
39- │ └── user/v1/user_service.py
40- └── main.py
31+ │ │ ├── adapters/
32+ │ │ │ ├── user_db_adapter.py
33+ │ │ │ └── user_cache_adapter.py
34+ │ │ └── user_repository.py
35+ │ ├── logics/
36+ │ │ └── user/
37+ │ │ ├── user_registration_logic.py
38+ │ │ └── user_query_logic.py
39+ │ └── services/
40+ │ └── user/v1/user_service.py
41+ │
42+ ├── features/ # BDD acceptance tests (behave)
43+ │ ├── user_registration.feature
44+ │ ├── steps/
45+ │ │ └── user_steps.py
46+ │ ├── scenario_context.py
47+ │ ├── scenario_context_pool_manager.py
48+ │ └── environment.py
49+ │
50+ └── manage.py # CLI entry point — click commands
4151```
4252
4353---
@@ -47,17 +57,23 @@ my_app/
4757``` python
4858# configs/app_config.py
4959from archipy.configs.base_config import BaseConfig
60+ from archipy.configs.environment_type import EnvironmentType
5061
5162
5263class AppConfig (BaseConfig ):
5364 """ Application-specific configuration.
5465
5566 All ArchiPy sections (REDIS, POSTGRES, FASTAPI, …) are inherited from BaseConfig.
56- Add custom fields below .
67+ Override `customize` to apply app-specific defaults after loading .
5768 """
5869
59- APP_NAME : str = " my-service"
60- DEBUG : bool = False
70+ def customize (self ) -> None :
71+ """ Apply app-specific configuration overrides."""
72+ super ().customize()
73+ self .FASTAPI .PROJECT_NAME = " my-service"
74+ self .FASTAPI .SERVE_HOST = " 0.0.0.0" # noqa: S104
75+ self .FASTAPI .SERVE_PORT = 8000
76+ self .FASTAPI .RELOAD = self .ENVIRONMENT == EnvironmentType.LOCAL
6177
6278
6379config = AppConfig()
@@ -653,27 +669,55 @@ def create_router(container: UserContainer) -> APIRouter:
653669
654670---
655671
656- ## Entry Point
672+ ## Entry Point: ` manage.py `
657673
658674``` python
659- # main.py
660- from archipy.helpers.utils.app_utils import AppUtils
675+ # manage.py
676+ import click
677+ import uvicorn
661678
662- import configs.app_config # noqa: F401 — importing triggers BaseConfig.set_global
679+ import configs.app_config # noqa: F401 — triggers BaseConfig.set_global
680+ from archipy.configs.base_config import BaseConfig
681+ from archipy.helpers.utils.app_utils import AppUtils
663682from configs.containers import UserContainer
664683from services.user.v1.user_service import create_router as create_user_v1_router
665684
666- user_container = UserContainer()
667685
668- app = AppUtils.create_fastapi_app()
669- app.include_router(create_user_v1_router(user_container))
686+ def create_app ():
687+ """ Create and configure the FastAPI application."""
688+ user_container = UserContainer()
689+ app = AppUtils.create_fastapi_app()
690+ app.include_router(create_user_v1_router(user_container))
691+ return app
670692
671- if __name__ == " __main__" :
672- import uvicorn
673- from archipy.configs.base_config import BaseConfig
674693
694+ @click.group ()
695+ def cli ():
696+ """ Management commands for my_app."""
697+
698+
699+ @cli.command ()
700+ @click.option (" --host" , default = None , show_default = True , help = " Bind host (defaults to FAST_API.SERVE_HOST)." )
701+ @click.option (" --port" , default = None , type = int , show_default = True , help = " Bind port (defaults to FAST_API.SERVE_PORT)." )
702+ @click.option (" --reload/--no-reload" , default = None , help = " Enable auto-reload (defaults to FAST_API.RELOAD)." )
703+ def run (host : str | None , port : int | None , reload : bool | None ) -> None :
704+ """ Start the FastAPI development server."""
675705 config = BaseConfig.global_config()
676- uvicorn.run(app, host = " 0.0.0.0" , port = 8000 ) # noqa: S104
706+ serve_host = host or config.FAST_API .SERVE_HOST
707+ serve_port = port or config.FAST_API .SERVE_PORT
708+ serve_reload = config.FAST_API .RELOAD if reload is None else reload
709+ uvicorn.run(" manage:create_app" , factory = True , host = serve_host, port = serve_port, reload = serve_reload)
710+
711+
712+ if __name__ == " __main__" :
713+ cli()
714+ ```
715+
716+ Run the server with:
717+
718+ ``` bash
719+ python manage.py run
720+ python manage.py run --port 9000 --reload
677721```
678722
679723---
0 commit comments