# 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]: ``` 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 ```