102 lines
3 KiB
Markdown
102 lines
3 KiB
Markdown
# Models
|
|
|
|
OhMyAPI uses [Tortoise](https://tortoise.github.io/) - an easy-to-use asyncio ORM (Object Relational Mapper) inspired by Django.
|
|
|
|
Models are exposed via a Python module named `models` in the app's directory.
|
|
OhMyAPI auto-detects all models exposed this way.
|
|
If the `models` module is a package, OhMyAPI will search through its submodules recursively.
|
|
|
|
## Writing models
|
|
|
|
### Your first simple model
|
|
|
|
```python
|
|
from ohmyapi.db import Model, field
|
|
|
|
|
|
class Restaurant(Model):
|
|
id: int = field.IntField(pk=True)
|
|
name: str = field.CharField(max_length=255)
|
|
description: str = field.TextField()
|
|
location: str = field.CharField(max_length=255)
|
|
```
|
|
|
|
### ForeignKeyRelations
|
|
|
|
You can define relationships between models.
|
|
|
|
```python
|
|
from ohmyapi.db import Model, field
|
|
|
|
from decimal import Decimal
|
|
|
|
|
|
class Restaurant(Model):
|
|
id: int = field.IntField(pk=True)
|
|
name: str = field.CharField(max_length=255)
|
|
description: str = field.TextField()
|
|
location: str = field.CharField(max_length=255)
|
|
|
|
|
|
class Dish(Model):
|
|
id: int = field.IntField(pk=True)
|
|
restaurant: field.ForeignKeyRelation[Restaurant] = field.ForeignKeyField(
|
|
"restaurant.Restaurant",
|
|
related_name="dishes",
|
|
)
|
|
name: str = field.CharField(max_length=255)
|
|
price: Decimal = field.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
|
|
class Order(Model):
|
|
id: int = field.IntField(pk=True)
|
|
restaurant: field.ForeignKeyRelation[Restaurant] = field.ForeignKeyField(
|
|
'restaurant.Restaurant',
|
|
related_name="dishes",
|
|
)
|
|
dishes: field.ManyToManyRelation[Dish] = field.ManyToManyField(
|
|
"restaurant.Dish",
|
|
relatated_name="orders",
|
|
through="dishesordered",
|
|
)
|
|
```
|
|
|
|
## Pydantic Schema Validation
|
|
|
|
Each model has a builtin `Schema` class that provides easy access to Pydantic models for schema validation.
|
|
Each model provides a default schema and a readonly schema, which you can obtain via the `get` method or by calling Schema() directly.
|
|
The default schema contains the full collection of fields of the Tortoise model.
|
|
The readonly schema excludes the primary-key field, as well as all readonly fields.
|
|
|
|
```python
|
|
In [1]: from restaurant.models import Restaurant
|
|
|
|
In [2]: Restaurant.Schema.get()
|
|
Out[2]: tortoise.contrib.pydantic.creator.RestaurantSchema
|
|
|
|
In [3]: Restaurant.Schema.get(readonly=True)
|
|
Out[3]: tortoise.contrib.pydantic.creator.RestaurantSchemaReadonly
|
|
|
|
In [4]: data = {
|
|
...: "name": "My Pizzeria",
|
|
...: "description": "Awesome Pizza!",
|
|
...: "location": "Berlin",
|
|
...: }
|
|
|
|
In [5]: Restaurant.Schema.get(readonly=True)(**data)
|
|
Out[5]: RestaurantSchemaReadonly(name='My Pizzeria', description='Awesome Pizza!', location='Berlin')
|
|
|
|
In [6]: Restaurant(**_.model_dump())
|
|
Out[6]: <Restaurant>
|
|
```
|
|
|
|
You can customize the fields to be include in the Pydantic schema:
|
|
|
|
```python
|
|
class MyModel(Model):
|
|
[...]
|
|
|
|
class Schema:
|
|
include: List[str] = [] # list of fields to include
|
|
exclude: List[str] = [] # list of fields to exclude
|
|
```
|