80 lines
2.1 KiB
Markdown
80 lines
2.1 KiB
Markdown
# CRUD Template
|
|
|
|
## Summary
|
|
|
|
Every resource follows the same four-file slice. Repetition is intentional: it
|
|
makes the codebase predictable and generatable.
|
|
|
|
---
|
|
|
|
## The slice
|
|
|
|
```
|
|
domain/<resource>/
|
|
models.py # pure Pydantic model (no DB fields)
|
|
ports/
|
|
db.py # document model + repository factory
|
|
service.py # service class + factory
|
|
converters.py # (optional) transforms
|
|
```
|
|
|
|
## models.py
|
|
|
|
A framework-free Pydantic model describing the business shape.
|
|
|
|
```python
|
|
class Item(BaseModel):
|
|
name: str
|
|
quantity: int = 0
|
|
```
|
|
|
|
## ports/db.py
|
|
|
|
The persistence model extends the business model and adds database concerns.
|
|
The repository factory selects the right repository flavour.
|
|
|
|
```python
|
|
class ItemDocument(Item, BaseDocument): # BaseDocument adds id/created_at/...
|
|
pass
|
|
|
|
def create_item_repo(*, owner_repo=None) -> ItemRepository:
|
|
return repo_factory(
|
|
collection="items",
|
|
document=ItemDocument,
|
|
populate_rules=[PopulateRule(field="owner", collection="users")],
|
|
cache=None, # or a CachedBaseRepository config
|
|
)
|
|
```
|
|
|
|
## ports/service.py
|
|
|
|
The service is built through the DI library, injecting the repository. The
|
|
generic CRUD base provides `create/read/update/patch/delete/search/...`.
|
|
|
|
```python
|
|
class ItemService(CrudsServiceAdaptor[Item, ItemDocument]):
|
|
model = Item
|
|
schema = ItemDocument
|
|
|
|
def get_item_service(repo) -> ItemService:
|
|
return build(ItemService, instances={"repo": repo})
|
|
```
|
|
|
|
## Naming conventions
|
|
|
|
| Concept | Convention |
|
|
|---|---|
|
|
| collection | plural snake case (`items`) |
|
|
| document | `<Resource>Document` |
|
|
| repository factory | `create_<resource>_repo` |
|
|
| service | `<Resource>Service` |
|
|
| service factory | `get_<resource>_service` |
|
|
| resource key | `<resource>_svc` |
|
|
| operationId | `list_items`, `create_item`, ... |
|
|
|
|
## Optional files
|
|
|
|
- `converters.py` — pure functions mapping between domain types.
|
|
- `ports/enrichment.py` — adapts a pipeline into an async callable the service
|
|
can invoke (used when a resource is populated by a pipeline).
|