# Python : Database : Tortoise : Cheatsheet
## Model Definition
Mixin classes are encouraged and do not need to inherit from Model and should not define a `Meta` inner class.
#### Meta
```python
MyModel < tortoise.Model
Meta:
abstract = False # set to True for base classes
app = "..." # if not explicitly set, will be set to owning app from config
schema = "..."
table = "..." # if not set, will be MyModel.__name__.lower()
table_description = "..."
unique_together = None | [ ( "f1", "f2" ), ... ]
indexes = None | [ ( "f1", "f2" ), ... ] # non-unique indexes
ordering = None | [ "[-]field1", ... ]
manager = instance of Manager or subclass
```
#### Fields
Can only have one PK, and if none specified, an integer PK named "id" will be added automatically.
```python
Field(
db_index = None # "should this field be indexed by itself?"
default = None # can be a callable; "default not part of the schema"
description = None
generated = False # whether value is DB-generated
model = None
null = False
primary_key = None
source_field = None | "COLUMN"
unique = False
validators = None
)
# if IntField w/primary_key = True, generated = True unless explicitly set to False
BigIntField()
BinaryField()
BooleanField()
CharEnumField( enum_type, max_length=0 )
CharField( max_length )
DateField()
DatetimeField( auto_now = False, auto_now_add = False )
DecimalField( max_digits, decimal_places )
FloatField()
IntEnumField( enum_type )
IntField()
JSONField( encoder=..., decoder=... )
SmallIntField()
TextField()
TimeDeltaField()
UUIDField()
ForeignKeyField(
model_name = "APP.MODEL"
related_name = None* | False | "..."
on_delete = CASCADE | RESTRICT | SET_NULL | SET_DEFAULT | NO_ACTION
db_constraint = True
null = True
to_field # defaults to pk
)
created = DatetimeField( auto_now_add = True ) # uses DEFAULT CURRENT_TIMESTAMP
modified = DatetimeField( auto_now = True ) # uses DEFAULT CURRENT_TIMESTAMP
```
#### Managers
TODO
## Model API
```python
Model.all( using_db=None ) -> QuerySet
Model.annotate( **kwargs ) -> QuerySet # annotate result set with extra Functions/Aggregations/Expressions
Model.bulk_create( objects, batch_size=None, ignore_conflicts=False, update_fields=None, on_conflict=None, using_db=None )
Model.bulk_update( objects, fields, batch_size=None, using_db=None )
~Model.create( using_db=None, **kwargs ) -> Model
Model.describe( serializable=True ) -> dict # True: json, False: raw python objects
Model.earliest( *orderings ) -> QuerySet # with filter that returns the first record
Model.exclude( *args, **kwargs ) -> querySet # with exclude applied
Model.exists( *args, using_db=None, **kwargs ) # args: Q functions containing constraints which are ANDed
# ex: await User.exists( username="foo" ) # kwargs: simple filter constraints
Model.fetch_for_list( instance_list, *args, using_db=None )
Model.fetch_related( *args, using_db=None )
Model.filter( *args, **kwargs )
Model.first( using_db=None )
Model.get( *args, using_db=None, **kwargs )
Model.get_or_create( defaults=None, using_db=None, **kwargs )
Model.get_or_none( *args, using_db=None, **kwargs )
Model.in_bulk( id_list, field_name="pk", using_db=None )
Model.last( using_db=None )
Model.latest( *orderings )
Model.pk # alias to model's PK
Model.raw( sql, using_db=None )
Model.register_listener( signal, listener )
Model.select_for_update( nowait=False, skip_locked=False, of=(), using_db=None )
Model.update_or_create( defaults=None, using_db=None, **kwargs )
```
## Instance API
```python
clone( pk=... )
~delete( using_db=None )
~refresh_from_db( fields=None, using_db=None )
~save( using_db=None, update_fields=None, force_create=False, force_update=False )
~update_from_dict( data )
```
#### Relations
```python
await tournament.events.all()
-or-
async for event in tournament.events:
TODO
```
## Querying
```python
Model.filter( foo_id__isnull=True )
TODO
```
## INBOX
```python
# sync usage requires that you call fetch_related() before:
await tournament.fetch_related( "events" )
len( tournament.events )
for event in tournament.events:
# the reverse must be pre-fetched (only supports sync interface)
event.fetch_related( "tournament" )
print( event.tournament )
### MANY-TO-MANY
async:
await tournament.participants.all()
-or-
async for p in tournament.participants:
sync:
tournament.fetch_related( "participants" )
len( tournament.participants )
for p in tournament.participants:
reverse works the same way
```