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