1 line
119 KiB
JSON
1 line
119 KiB
JSON
{"config":{"lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"ormar Overview The ormar package is an async mini ORM for Python, with support for Postgres, MySQL , and SQLite . The main benefit of using ormar are: getting an async ORM that can be used with async frameworks (fastapi, starlette etc.) getting just one model to maintain - you don't have to maintain pydantic and other orm model (sqlalchemy, peewee, gino etc.) The goal was to create a simple ORM that can be used directly (as request and response models) with fastapi that bases it's data validation on pydantic. Ormar - apart form obvious ORM in name - get it's name from ormar in swedish which means snakes, and ormar(e) in italian which means cabinet. And what's a better name for python ORM than snakes cabinet :) Documentation Check out the documentation for details. Dependencies Ormar is built with: SQLAlchemy core for query building. databases for cross-database async support. pydantic for data validation. Migrations Because ormar is built on SQLAlchemy core, you can use alembic to provide database migrations. ormar is still under development: We recommend pinning any dependencies with ormar~=0.3.6 Quick Start Note : Use ipython to try this from the console, since it supports await . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Album ( ormar . Model ): class Meta : tablename = \"album\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) name : ormar . String ( length = 100 ) class Track ( ormar . Model ): class Meta : tablename = \"track\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) album : ormar . ForeignKey ( Album ) title : ormar . String ( length = 100 ) position : ormar . Integer () # Create some records to work with. malibu = await Album . objects . create ( name = \"Malibu\" ) await Track . objects . create ( album = malibu , title = \"The Bird\" , position = 1 ) await Track . objects . create ( album = malibu , title = \"Heart don't stand a chance\" , position = 2 ) await Track . objects . create ( album = malibu , title = \"The Waters\" , position = 3 ) fantasies = await Album . objects . create ( name = \"Fantasies\" ) await Track . objects . create ( album = fantasies , title = \"Help I'm Alive\" , position = 1 ) await Track . objects . create ( album = fantasies , title = \"Sick Muse\" , position = 2 ) # Fetch an instance, without loading a foreign key relationship on it. track = await Track . objects . get ( title = \"The Bird\" ) # We have an album instance, but it only has the primary key populated print ( track . album ) # Album(id=1) [sparse] print ( track . album . pk ) # 1 print ( track . album . name ) # None # Load the relationship from the database await track . album . load () assert track . album . name == \"Malibu\" # This time, fetch an instance, loading the foreign key relationship. track = await Track . objects . select_related ( \"album\" ) . get ( title = \"The Bird\" ) assert track . album . name == \"Malibu\" # By default you also get a second side of the relation # constructed as lowercase source model name +'s' (tracks in this case) # you can also provide custom name with parameter related_name album = await Album . objects . select_related ( \"tracks\" ) . all () assert len ( album . tracks ) == 3 # Fetch instances, with a filter across an FK relationship. tracks = Track . objects . filter ( album__name = \"Fantasies\" ) assert len ( tracks ) == 2 # Fetch instances, with a filter and operator across an FK relationship. tracks = Track . objects . filter ( album__name__iexact = \"fantasies\" ) assert len ( tracks ) == 2 # Limit a query tracks = await Track . objects . limit ( 1 ) . all () assert len ( tracks ) == 1 Data types Relation types One to many - with ForeignKey Many to many - with Many2Many Model fields types Available Model Fields (with required args - optional ones in docs): String(max_length) Text() Boolean() Integer() Float() Date() Time() DateTime() JSON() BigInteger() Decimal(scale, precision) UUID() ForeignKey(to) Many2Many(to, through) Available fields options The following keyword arguments are supported on all field types. primary_key: bool nullable: bool default: Any server_default: Any index: bool unique: bool choices: typing.Sequence All fields are required unless one of the following is set: nullable - Creates a nullable column. Sets the default to None . default - Set a default value for the field. server_default - Set a default value for the field on server side (like sqlalchemy's func.now() ). primary key with autoincrement - When a column is set to primary key and autoincrement is set on this column. Autoincrement is set by default on int primary keys.","title":"Overview"},{"location":"#ormar","text":"","title":"ormar"},{"location":"#overview","text":"The ormar package is an async mini ORM for Python, with support for Postgres, MySQL , and SQLite . The main benefit of using ormar are: getting an async ORM that can be used with async frameworks (fastapi, starlette etc.) getting just one model to maintain - you don't have to maintain pydantic and other orm model (sqlalchemy, peewee, gino etc.) The goal was to create a simple ORM that can be used directly (as request and response models) with fastapi that bases it's data validation on pydantic. Ormar - apart form obvious ORM in name - get it's name from ormar in swedish which means snakes, and ormar(e) in italian which means cabinet. And what's a better name for python ORM than snakes cabinet :)","title":"Overview"},{"location":"#documentation","text":"Check out the documentation for details.","title":"Documentation"},{"location":"#dependencies","text":"Ormar is built with: SQLAlchemy core for query building. databases for cross-database async support. pydantic for data validation.","title":"Dependencies"},{"location":"#migrations","text":"Because ormar is built on SQLAlchemy core, you can use alembic to provide database migrations. ormar is still under development: We recommend pinning any dependencies with ormar~=0.3.6","title":"Migrations"},{"location":"#quick-start","text":"Note : Use ipython to try this from the console, since it supports await . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Album ( ormar . Model ): class Meta : tablename = \"album\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) name : ormar . String ( length = 100 ) class Track ( ormar . Model ): class Meta : tablename = \"track\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) album : ormar . ForeignKey ( Album ) title : ormar . String ( length = 100 ) position : ormar . Integer () # Create some records to work with. malibu = await Album . objects . create ( name = \"Malibu\" ) await Track . objects . create ( album = malibu , title = \"The Bird\" , position = 1 ) await Track . objects . create ( album = malibu , title = \"Heart don't stand a chance\" , position = 2 ) await Track . objects . create ( album = malibu , title = \"The Waters\" , position = 3 ) fantasies = await Album . objects . create ( name = \"Fantasies\" ) await Track . objects . create ( album = fantasies , title = \"Help I'm Alive\" , position = 1 ) await Track . objects . create ( album = fantasies , title = \"Sick Muse\" , position = 2 ) # Fetch an instance, without loading a foreign key relationship on it. track = await Track . objects . get ( title = \"The Bird\" ) # We have an album instance, but it only has the primary key populated print ( track . album ) # Album(id=1) [sparse] print ( track . album . pk ) # 1 print ( track . album . name ) # None # Load the relationship from the database await track . album . load () assert track . album . name == \"Malibu\" # This time, fetch an instance, loading the foreign key relationship. track = await Track . objects . select_related ( \"album\" ) . get ( title = \"The Bird\" ) assert track . album . name == \"Malibu\" # By default you also get a second side of the relation # constructed as lowercase source model name +'s' (tracks in this case) # you can also provide custom name with parameter related_name album = await Album . objects . select_related ( \"tracks\" ) . all () assert len ( album . tracks ) == 3 # Fetch instances, with a filter across an FK relationship. tracks = Track . objects . filter ( album__name = \"Fantasies\" ) assert len ( tracks ) == 2 # Fetch instances, with a filter and operator across an FK relationship. tracks = Track . objects . filter ( album__name__iexact = \"fantasies\" ) assert len ( tracks ) == 2 # Limit a query tracks = await Track . objects . limit ( 1 ) . all () assert len ( tracks ) == 1","title":"Quick Start"},{"location":"#data-types","text":"","title":"Data types"},{"location":"#relation-types","text":"One to many - with ForeignKey Many to many - with Many2Many","title":"Relation types"},{"location":"#model-fields-types","text":"Available Model Fields (with required args - optional ones in docs): String(max_length) Text() Boolean() Integer() Float() Date() Time() DateTime() JSON() BigInteger() Decimal(scale, precision) UUID() ForeignKey(to) Many2Many(to, through)","title":"Model fields types"},{"location":"#available-fields-options","text":"The following keyword arguments are supported on all field types. primary_key: bool nullable: bool default: Any server_default: Any index: bool unique: bool choices: typing.Sequence All fields are required unless one of the following is set: nullable - Creates a nullable column. Sets the default to None . default - Set a default value for the field. server_default - Set a default value for the field on server side (like sqlalchemy's func.now() ). primary key with autoincrement - When a column is set to primary key and autoincrement is set on this column. Autoincrement is set by default on int primary keys.","title":"Available fields options"},{"location":"contributing/","text":"All contributions to ormar are welcomed! Issues To make it as simple as possible for us to help you, please include the following: OS python version ormar version database backend (mysql, sqlite or postgresql) Please try to always include the above unless you're unable to install ormar or know it's not relevant to your question or feature request. Pull Requests It should be quite straight forward to get started and create a Pull Request. Note Unless your change is trivial (typo, docs tweak etc.), please create an issue to discuss the change before creating a pull request. To make contributing as easy and fast as possible, you'll want to run tests and linting locally. You'll need to have python 3.6 , 3.7 , or 3.8 , virtualenv , and git installed. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 # 1. clone your fork and cd into the repo directory git clone git@github.com:<your username>/ormar.git cd ormar # 2. Set up a virtualenv for running tests virtualenv -p ` which python3.7 ` env source env/bin/activate # (or however you prefer to setup a python environment, 3.6 will work too) # 3. Install ormar, dependencies and test dependencies pip install -r requirements.txt # 4. Checkout a new branch and make your changes git checkout -b my-new-feature-branch # make your changes... # 5. Formatting and linting # ormar uses black for formatting, flake8 for linting and mypy for type hints check # run all of the following as all those calls will be run on travis after every push black ormar flake8 ormar mypy --config-file mypy.ini ormar # 6. Run tests # on localhost all tests are run against sglite backend # rest of the backends will be checked after push pytest -svv --cov = ormar --cov = tests --cov-fail-under = 100 --cov-report = term-missing # 7. Build documentation mkdocs build # if you have changed the documentation make sure it builds successfully # you can also use `mkdocs serve` to serve the documentation at localhost:8000 # ... commit, push, and create your pull request","title":"Contributing"},{"location":"contributing/#issues","text":"To make it as simple as possible for us to help you, please include the following: OS python version ormar version database backend (mysql, sqlite or postgresql) Please try to always include the above unless you're unable to install ormar or know it's not relevant to your question or feature request.","title":"Issues"},{"location":"contributing/#pull-requests","text":"It should be quite straight forward to get started and create a Pull Request. Note Unless your change is trivial (typo, docs tweak etc.), please create an issue to discuss the change before creating a pull request. To make contributing as easy and fast as possible, you'll want to run tests and linting locally. You'll need to have python 3.6 , 3.7 , or 3.8 , virtualenv , and git installed. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 # 1. clone your fork and cd into the repo directory git clone git@github.com:<your username>/ormar.git cd ormar # 2. Set up a virtualenv for running tests virtualenv -p ` which python3.7 ` env source env/bin/activate # (or however you prefer to setup a python environment, 3.6 will work too) # 3. Install ormar, dependencies and test dependencies pip install -r requirements.txt # 4. Checkout a new branch and make your changes git checkout -b my-new-feature-branch # make your changes... # 5. Formatting and linting # ormar uses black for formatting, flake8 for linting and mypy for type hints check # run all of the following as all those calls will be run on travis after every push black ormar flake8 ormar mypy --config-file mypy.ini ormar # 6. Run tests # on localhost all tests are run against sglite backend # rest of the backends will be checked after push pytest -svv --cov = ormar --cov = tests --cov-fail-under = 100 --cov-report = term-missing # 7. Build documentation mkdocs build # if you have changed the documentation make sure it builds successfully # you can also use `mkdocs serve` to serve the documentation at localhost:8000 # ... commit, push, and create your pull request","title":"Pull Requests"},{"location":"fastapi/","text":"The use of ormar with fastapi is quite simple. Apart from connecting to databases at startup everything else you need to do is substitute pydantic models with ormar models. Here you can find a very simple sample application code. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 from typing import List import databases import pytest import sqlalchemy from fastapi import FastAPI from starlette.testclient import TestClient import ormar from tests.settings import DATABASE_URL app = FastAPI () metadata = sqlalchemy . MetaData () database = databases . Database ( DATABASE_URL , force_rollback = True ) app . state . database = database # define startup and shutdown events @app . on_event ( \"startup\" ) async def startup () -> None : database_ = app . state . database if not database_ . is_connected : await database_ . connect () @app . on_event ( \"shutdown\" ) async def shutdown () -> None : database_ = app . state . database if database_ . is_connected : await database_ . disconnect () # define ormar models class Category ( ormar . Model ): class Meta : tablename = \"categories\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Item ( ormar . Model ): class Meta : tablename = \"items\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) category : ormar . ForeignKey ( Category , nullable = True ) # define endpoints in fastapi @app . get ( \"/items/\" , response_model = List [ Item ]) async def get_items (): items = await Item . objects . select_related ( \"category\" ) . all () # not that you can return a model directly - fastapi will json-ize it return items @app . post ( \"/items/\" , response_model = Item ) async def create_item ( item : Item ): # note how ormar methods like save() are available streight out of the box await item . save () return item @app . post ( \"/categories/\" , response_model = Category ) async def create_category ( category : Category ): await category . save () return category @app . put ( \"/items/ {item_id} \" ) async def get_item ( item_id : int , item : Item ): # you can work both with item_id or item item_db = await Item . objects . get ( pk = item_id ) return await item_db . update ( ** item . dict ()) @app . delete ( \"/items/ {item_id} \" ) async def delete_item ( item_id : int , item : Item ): item_db = await Item . objects . get ( pk = item_id ) return { \"deleted_rows\" : await item_db . delete ()} # here is a sample test to check the working of the ormar with fastapi def test_all_endpoints (): # note that TestClient is only sync, don't use asyns here client = TestClient ( app ) # note that you need to connect to database manually # or use client as contextmanager with client as client : response = client . post ( \"/categories/\" , json = { \"name\" : \"test cat\" }) category = response . json () response = client . post ( \"/items/\" , json = { \"name\" : \"test\" , \"id\" : 1 , \"category\" : category } ) item = Item ( ** response . json ()) assert item . pk is not None response = client . get ( \"/items/\" ) items = [ Item ( ** item ) for item in response . json ()] assert items [ 0 ] == item item . name = \"New name\" response = client . put ( f \"/items/ { item . pk } \" , json = item . dict ()) assert response . json () == item . dict () response = client . get ( \"/items/\" ) items = [ Item ( ** item ) for item in response . json ()] assert items [ 0 ] . name == \"New name\" response = client . delete ( f \"/items/ { item . pk } \" , json = item . dict ()) assert response . json () . get ( \"deleted_rows\" , \"__UNDEFINED__\" ) != \"__UNDEFINED__\" response = client . get ( \"/items/\" ) items = response . json () assert len ( items ) == 0","title":"Use with Fastapi"},{"location":"fields/","text":"Fields There are 12 basic model field types and a special ForeignKey and Many2Many fields to establish relationships between models. Tip For explanation of ForeignKey and Many2Many fields check relations . Each of the Fields has assigned both sqlalchemy column class and python type that is used to create pydantic model. Common Parameters All Field types have a set of common parameters. primary_key primary_key : bool = False -> by default False. Sets the primary key column on a table, foreign keys always refer to the pk of the Model . Used in sql only. autoincrement autoincrement : bool = primary_key and type == int -> defaults to True if column is a primary key and of type Integer, otherwise False. Can be only used with int/bigint fields. If a field has autoincrement it becomes optional. Used both in sql and pydantic (changes pk field to optional for autoincrement). nullable nullable : bool = not primary_key -> defaults to False for primary key column, and True for all other. Specifies if field is optional or required, used both with sql and pydantic. Note By default all ForeignKeys are also nullable, meaning the related Model is not required. If you change the ForeignKey column to nullable=False , it becomes required. Info If you want to know more about how you can preload related models during queries and how the relations work read the queries and relations sections. default default : Any = None -> defaults to None. A default value used if no other value is passed. In sql invoked on an insert, used during pydantic model definition. If the field has a default value it becomes optional. You can pass a static value or a Callable (function etc.) Used both in sql and pydantic. server default server_default : Any = None -> defaults to None. A default value used if no other value is passed. In sql invoked on the server side so you can pass i.e. sql function (like now() wrapped in sqlalchemy text() clause). If the field has a server_default value it becomes optional. You can pass a static value or a Callable (function etc.) Used in sql only. index index : bool = False -> by default False, Sets the index on a table's column. Used in sql only. unique unique : bool = False Sets the unique constraint on a table's column. Used in sql only. pydantic_only pydantic_only : bool = False Prevents creation of a sql column for given field. Used for data related to given model but not to be stored in the database. Used in pydantic only. choices choices : Sequence = [] A set of choices allowed to be used for given field. Used for data validation on pydantic side. Prevents insertion of value not present in the choices list. Used in pydantic only. Fields Types String String(max_length, allow_blank: bool = True, strip_whitespace: bool = False, min_length: int = None, max_length: int = None, curtail_length: int = None, regex: str = None,) has a required max_length parameter. Sqlalchemy column: sqlalchemy.String Type (used for pydantic): str Tip For explanation of other parameters check pydantic documentation. Text Text(allow_blank: bool = True, strip_whitespace: bool = False) has no required parameters. Sqlalchemy column: sqlalchemy.Text Type (used for pydantic): str Tip For explanation of other parameters check pydantic documentation. Boolean Boolean() has no required parameters. Sqlalchemy column: sqlalchemy.Boolean Type (used for pydantic): bool Integer Integer(minimum: int = None, maximum: int = None, multiple_of: int = None) has no required parameters. Sqlalchemy column: sqlalchemy.Integer Type (used for pydantic): int Tip For explanation of other parameters check pydantic documentation. BigInteger BigInteger(minimum: int = None, maximum: int = None, multiple_of: int = None) has no required parameters. Sqlalchemy column: sqlalchemy.BigInteger Type (used for pydantic): int Tip For explanation of other parameters check pydantic documentation. Float Float(minimum: float = None, maximum: float = None, multiple_of: int = None) has no required parameters. Sqlalchemy column: sqlalchemy.Float Type (used for pydantic): float Tip For explanation of other parameters check pydantic documentation. Decimal Decimal(minimum: float = None, maximum: float = None, multiple_of: int = None, precision: int = None, scale: int = None, max_digits: int = None, decimal_places: int = None) has no required parameters You can use either length and precision parameters or max_digits and decimal_places . Sqlalchemy column: sqlalchemy.DECIMAL Type (used for pydantic): decimal.Decimal Tip For explanation of other parameters check pydantic documentation. Date Date() has no required parameters. Sqlalchemy column: sqlalchemy.Date Type (used for pydantic): datetime.date Time Time() has no required parameters. Sqlalchemy column: sqlalchemy.Time Type (used for pydantic): datetime.time DateTime DateTime() has no required parameters. Sqlalchemy column: sqlalchemy.DateTime Type (used for pydantic): datetime.datetime JSON JSON() has no required parameters. Sqlalchemy column: sqlalchemy.JSON Type (used for pydantic): pydantic.Json UUID UUID() has no required parameters. Sqlalchemy column: ormar.UUID based on sqlalchemy.CHAR field Type (used for pydantic): uuid.UUID","title":"Fields"},{"location":"fields/#fields","text":"There are 12 basic model field types and a special ForeignKey and Many2Many fields to establish relationships between models. Tip For explanation of ForeignKey and Many2Many fields check relations . Each of the Fields has assigned both sqlalchemy column class and python type that is used to create pydantic model.","title":"Fields"},{"location":"fields/#common-parameters","text":"All Field types have a set of common parameters.","title":"Common Parameters"},{"location":"fields/#primary_key","text":"primary_key : bool = False -> by default False. Sets the primary key column on a table, foreign keys always refer to the pk of the Model . Used in sql only.","title":"primary_key"},{"location":"fields/#autoincrement","text":"autoincrement : bool = primary_key and type == int -> defaults to True if column is a primary key and of type Integer, otherwise False. Can be only used with int/bigint fields. If a field has autoincrement it becomes optional. Used both in sql and pydantic (changes pk field to optional for autoincrement).","title":"autoincrement"},{"location":"fields/#nullable","text":"nullable : bool = not primary_key -> defaults to False for primary key column, and True for all other. Specifies if field is optional or required, used both with sql and pydantic. Note By default all ForeignKeys are also nullable, meaning the related Model is not required. If you change the ForeignKey column to nullable=False , it becomes required. Info If you want to know more about how you can preload related models during queries and how the relations work read the queries and relations sections.","title":"nullable"},{"location":"fields/#default","text":"default : Any = None -> defaults to None. A default value used if no other value is passed. In sql invoked on an insert, used during pydantic model definition. If the field has a default value it becomes optional. You can pass a static value or a Callable (function etc.) Used both in sql and pydantic.","title":"default"},{"location":"fields/#server-default","text":"server_default : Any = None -> defaults to None. A default value used if no other value is passed. In sql invoked on the server side so you can pass i.e. sql function (like now() wrapped in sqlalchemy text() clause). If the field has a server_default value it becomes optional. You can pass a static value or a Callable (function etc.) Used in sql only.","title":"server default"},{"location":"fields/#index","text":"index : bool = False -> by default False, Sets the index on a table's column. Used in sql only.","title":"index"},{"location":"fields/#unique","text":"unique : bool = False Sets the unique constraint on a table's column. Used in sql only.","title":"unique"},{"location":"fields/#pydantic_only","text":"pydantic_only : bool = False Prevents creation of a sql column for given field. Used for data related to given model but not to be stored in the database. Used in pydantic only.","title":"pydantic_only"},{"location":"fields/#choices","text":"choices : Sequence = [] A set of choices allowed to be used for given field. Used for data validation on pydantic side. Prevents insertion of value not present in the choices list. Used in pydantic only.","title":"choices"},{"location":"fields/#fields-types","text":"","title":"Fields Types"},{"location":"fields/#string","text":"String(max_length, allow_blank: bool = True, strip_whitespace: bool = False, min_length: int = None, max_length: int = None, curtail_length: int = None, regex: str = None,) has a required max_length parameter. Sqlalchemy column: sqlalchemy.String Type (used for pydantic): str Tip For explanation of other parameters check pydantic documentation.","title":"String"},{"location":"fields/#text","text":"Text(allow_blank: bool = True, strip_whitespace: bool = False) has no required parameters. Sqlalchemy column: sqlalchemy.Text Type (used for pydantic): str Tip For explanation of other parameters check pydantic documentation.","title":"Text"},{"location":"fields/#boolean","text":"Boolean() has no required parameters. Sqlalchemy column: sqlalchemy.Boolean Type (used for pydantic): bool","title":"Boolean"},{"location":"fields/#integer","text":"Integer(minimum: int = None, maximum: int = None, multiple_of: int = None) has no required parameters. Sqlalchemy column: sqlalchemy.Integer Type (used for pydantic): int Tip For explanation of other parameters check pydantic documentation.","title":"Integer"},{"location":"fields/#biginteger","text":"BigInteger(minimum: int = None, maximum: int = None, multiple_of: int = None) has no required parameters. Sqlalchemy column: sqlalchemy.BigInteger Type (used for pydantic): int Tip For explanation of other parameters check pydantic documentation.","title":"BigInteger"},{"location":"fields/#float","text":"Float(minimum: float = None, maximum: float = None, multiple_of: int = None) has no required parameters. Sqlalchemy column: sqlalchemy.Float Type (used for pydantic): float Tip For explanation of other parameters check pydantic documentation.","title":"Float"},{"location":"fields/#decimal","text":"Decimal(minimum: float = None, maximum: float = None, multiple_of: int = None, precision: int = None, scale: int = None, max_digits: int = None, decimal_places: int = None) has no required parameters You can use either length and precision parameters or max_digits and decimal_places . Sqlalchemy column: sqlalchemy.DECIMAL Type (used for pydantic): decimal.Decimal Tip For explanation of other parameters check pydantic documentation.","title":"Decimal"},{"location":"fields/#date","text":"Date() has no required parameters. Sqlalchemy column: sqlalchemy.Date Type (used for pydantic): datetime.date","title":"Date"},{"location":"fields/#time","text":"Time() has no required parameters. Sqlalchemy column: sqlalchemy.Time Type (used for pydantic): datetime.time","title":"Time"},{"location":"fields/#datetime","text":"DateTime() has no required parameters. Sqlalchemy column: sqlalchemy.DateTime Type (used for pydantic): datetime.datetime","title":"DateTime"},{"location":"fields/#json","text":"JSON() has no required parameters. Sqlalchemy column: sqlalchemy.JSON Type (used for pydantic): pydantic.Json","title":"JSON"},{"location":"fields/#uuid","text":"UUID() has no required parameters. Sqlalchemy column: ormar.UUID based on sqlalchemy.CHAR field Type (used for pydantic): uuid.UUID","title":"UUID"},{"location":"install/","text":"Installation Installation is as simple as: 1 pip install ormar Dependencies Ormar uses databases for connectivity issues, pydantic for validation and sqlalchemy-core for queries. All three should install along the installation of ormar if not present at your system before. databases pydantic>=1.5 sqlalchemy Optional dependencies ormar has three optional dependencies based on database backend you use: Postgresql 1 pip install ormar [ postgresql ] Mysql Will install also asyncpg and psycopg2 . 1 pip install ormar [ mysql ] Will install also aiomysql and pymysql . Sqlite 1 pip install ormar [ sqlite ] Will install also aiosqlite . Manual installation of dependencies Of course, you can also install these requirements manually with pip install asyncpg etc.","title":"Installation"},{"location":"install/#installation","text":"Installation is as simple as: 1 pip install ormar","title":"Installation"},{"location":"install/#dependencies","text":"Ormar uses databases for connectivity issues, pydantic for validation and sqlalchemy-core for queries. All three should install along the installation of ormar if not present at your system before. databases pydantic>=1.5 sqlalchemy","title":"Dependencies"},{"location":"install/#optional-dependencies","text":"ormar has three optional dependencies based on database backend you use:","title":"Optional dependencies"},{"location":"install/#postgresql","text":"1 pip install ormar [ postgresql ]","title":"Postgresql"},{"location":"install/#mysql","text":"Will install also asyncpg and psycopg2 . 1 pip install ormar [ mysql ] Will install also aiomysql and pymysql .","title":"Mysql"},{"location":"install/#sqlite","text":"1 pip install ormar [ sqlite ] Will install also aiosqlite .","title":"Sqlite"},{"location":"install/#manual-installation-of-dependencies","text":"Of course, you can also install these requirements manually with pip install asyncpg etc.","title":"Manual installation of dependencies"},{"location":"models/","text":"Models Defining models By defining an ormar Model you get corresponding Pydantic model as well as Sqlalchemy table for free. They are being managed in the background and you do not have to create them on your own. Model Class To build an ormar model you simply need to inherit a ormar.Model class. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) Defining Fields Next assign one or more of the Fields as a class level variables. Each table has to have a primary key column, which you specify by setting primary_key=True on selected field. Only one primary key column is allowed. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) Warning Not assigning primary_key column or assigning more than one column per Model will raise ModelDefinitionError exception. By default if you assign primary key to Integer field, the autoincrement option is set to true. You can disable by passing autoincremant=False . 1 id : ormar . Integer ( primary_key = True , autoincrement = False ) Names of the fields will be used for both the underlying pydantic model and sqlalchemy table. Dependencies Since ormar depends on databases and sqlalchemy-core for database connection and table creation you need to assign each Model with two special parameters. Databases One is Database instance created with your database url in sqlalchemy connection string format. Created instance needs to be passed to every Model with Meta class database parameter. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) Tip You need to create the Database instance only once and use it for all models. You can create several ones if you want to use multiple databases. Sqlalchemy Second dependency is sqlalchemy MetaData instance. Created instance needs to be passed to every Model with Meta class metadata parameter. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) Tip You need to create the MetaData instance only once and use it for all models. You can create several ones if you want to use multiple databases. Table Names By default table name is created from Model class name as lowercase name plus 's'. You can overwrite this parameter by providing Meta class tablename argument. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : # if you omit this parameter it will be created automatically # as class.__name__.lower()+'s' -> \"courses\" in this example tablename = \"my_courses\" database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) Constraints On a model level you can also set model-wise constraints on sql columns. Right now only UniqueColumns constraint is present. Tip To read more about columns constraints like primary_key , unique , ForeignKey etc. visit fields . You can set this parameter by providing Meta class constraints argument. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata # define your constraints in Meta class of the model # it's a list that can contain multiple constraints # hera a combination of name and column will have to be unique in db constraints = [ ormar . UniqueColumns ( 'name' , 'completed' )] id = ormar . Integer ( primary_key = True ) name = ormar . String ( max_length = 100 ) completed = ormar . Boolean ( default = False ) Initialization There are two ways to create and persist the Model instance in the database. Tip Use ipython to try this from the console, since it supports await . If you plan to modify the instance in the later execution of your program you can initiate your Model as a normal class and later await a save() call. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id = ormar . Integer ( primary_key = True ) name = ormar . String ( max_length = 100 ) completed = ormar . Boolean ( default = False ) course = Course ( name = \"Painting for dummies\" , completed = False ) await course . save () await Course . objects . create ( name = \"Painting for dummies\" , completed = False ) If you want to initiate your Model and at the same time save in in the database use a QuerySet's method create() . For creating multiple objects at once a bulk_create() QuerySet's method is available. Each model has a QuerySet initialised as objects parameter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id = ormar . Integer ( primary_key = True ) name = ormar . String ( max_length = 100 ) completed = ormar . Boolean ( default = False ) course = Course ( name = \"Painting for dummies\" , completed = False ) await course . save () await Course . objects . create ( name = \"Painting for dummies\" , completed = False ) Info To read more about QuerySets (including bulk operations) and available methods visit queries Model methods load By default when you query a table without prefetching related models, the ormar will still construct your related models, but populate them only with the pk value. 1 2 3 4 5 6 7 track = await Track . objects . get ( name = 'The Bird' ) track . album . pk # will return malibu album pk (1) track . album . name # will return None # you need to actually load the data first await track . album . load () track . album . name # will return 'Malibu' save delete update Internals Apart from special parameters defined in the Model during definition (tablename, metadata etc.) the Model provides you with useful internals. Pydantic Model All Model classes inherit from pydantic.BaseModel so you can access all normal attributes of pydantic models. For example to list pydantic model fields you can: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) print ( Course . __fields__ ) \"\"\" Will produce: {'id': ModelField(name='id', type=Optional[int], required=False, default=None), 'name': ModelField(name='name', type=Optional[str], required=False, default=None), 'completed': ModelField(name='completed', type=bool, required=False, default=False)} \"\"\" Tip Note how the primary key id field is optional as Integer primary key by default has autoincrement set to True . Info For more options visit official pydantic documentation. Sqlalchemy Table To access auto created sqlalchemy table you can use Model.Meta.table parameter For example to list table columns you can: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) print ( Course . Meta . table . columns ) \"\"\" Will produce: ['courses.id', 'courses.name', 'courses.completed'] \"\"\" Tip You can access table primary key name by Course.Meta.pkname Info For more options visit official sqlalchemy-metadata documentation. Fields Definition To access ormar Fields you can use Model.Meta.model_fields parameter For example to list table model fields you can: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) print ({ x : v . __dict__ for x , v in Course . Meta . model_fields . items ()}) \"\"\" Will produce: {'completed': mappingproxy({'autoincrement': False, 'choices': set(), 'column_type': Boolean(), 'default': False, 'index': False, 'name': 'completed', 'nullable': True, 'primary_key': False, 'pydantic_only': False, 'server_default': None, 'unique': False}), 'id': mappingproxy({'autoincrement': True, 'choices': set(), 'column_type': Integer(), 'default': None, 'ge': None, 'index': False, 'le': None, 'maximum': None, 'minimum': None, 'multiple_of': None, 'name': 'id', 'nullable': False, 'primary_key': True, 'pydantic_only': False, 'server_default': None, 'unique': False}), 'name': mappingproxy({'allow_blank': False, 'autoincrement': False, 'choices': set(), 'column_type': String(length=100), 'curtail_length': None, 'default': None, 'index': False, 'max_length': 100, 'min_length': None, 'name': 'name', 'nullable': False, 'primary_key': False, 'pydantic_only': False, 'regex': None, 'server_default': None, 'strip_whitespace': False, 'unique': False})} \"\"\" Info Note that fields stored on a model are classes not instances . So if you print just model fields you will get: {'id': <class 'ormar.fields.model_fields.Integer'>, 'name': <class 'ormar.fields.model_fields.String'>, 'completed': <class 'ormar.fields.model_fields.Boolean'>}","title":"Models"},{"location":"models/#models","text":"","title":"Models"},{"location":"models/#defining-models","text":"By defining an ormar Model you get corresponding Pydantic model as well as Sqlalchemy table for free. They are being managed in the background and you do not have to create them on your own.","title":"Defining models"},{"location":"models/#model-class","text":"To build an ormar model you simply need to inherit a ormar.Model class. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False )","title":"Model Class"},{"location":"models/#defining-fields","text":"Next assign one or more of the Fields as a class level variables. Each table has to have a primary key column, which you specify by setting primary_key=True on selected field. Only one primary key column is allowed. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) Warning Not assigning primary_key column or assigning more than one column per Model will raise ModelDefinitionError exception. By default if you assign primary key to Integer field, the autoincrement option is set to true. You can disable by passing autoincremant=False . 1 id : ormar . Integer ( primary_key = True , autoincrement = False ) Names of the fields will be used for both the underlying pydantic model and sqlalchemy table.","title":"Defining Fields"},{"location":"models/#dependencies","text":"Since ormar depends on databases and sqlalchemy-core for database connection and table creation you need to assign each Model with two special parameters.","title":"Dependencies"},{"location":"models/#databases","text":"One is Database instance created with your database url in sqlalchemy connection string format. Created instance needs to be passed to every Model with Meta class database parameter. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) Tip You need to create the Database instance only once and use it for all models. You can create several ones if you want to use multiple databases.","title":"Databases"},{"location":"models/#sqlalchemy","text":"Second dependency is sqlalchemy MetaData instance. Created instance needs to be passed to every Model with Meta class metadata parameter. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) Tip You need to create the MetaData instance only once and use it for all models. You can create several ones if you want to use multiple databases.","title":"Sqlalchemy"},{"location":"models/#table-names","text":"By default table name is created from Model class name as lowercase name plus 's'. You can overwrite this parameter by providing Meta class tablename argument. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : # if you omit this parameter it will be created automatically # as class.__name__.lower()+'s' -> \"courses\" in this example tablename = \"my_courses\" database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False )","title":"Table Names"},{"location":"models/#constraints","text":"On a model level you can also set model-wise constraints on sql columns. Right now only UniqueColumns constraint is present. Tip To read more about columns constraints like primary_key , unique , ForeignKey etc. visit fields . You can set this parameter by providing Meta class constraints argument. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata # define your constraints in Meta class of the model # it's a list that can contain multiple constraints # hera a combination of name and column will have to be unique in db constraints = [ ormar . UniqueColumns ( 'name' , 'completed' )] id = ormar . Integer ( primary_key = True ) name = ormar . String ( max_length = 100 ) completed = ormar . Boolean ( default = False )","title":"Constraints"},{"location":"models/#initialization","text":"There are two ways to create and persist the Model instance in the database. Tip Use ipython to try this from the console, since it supports await . If you plan to modify the instance in the later execution of your program you can initiate your Model as a normal class and later await a save() call. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id = ormar . Integer ( primary_key = True ) name = ormar . String ( max_length = 100 ) completed = ormar . Boolean ( default = False ) course = Course ( name = \"Painting for dummies\" , completed = False ) await course . save () await Course . objects . create ( name = \"Painting for dummies\" , completed = False ) If you want to initiate your Model and at the same time save in in the database use a QuerySet's method create() . For creating multiple objects at once a bulk_create() QuerySet's method is available. Each model has a QuerySet initialised as objects parameter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id = ormar . Integer ( primary_key = True ) name = ormar . String ( max_length = 100 ) completed = ormar . Boolean ( default = False ) course = Course ( name = \"Painting for dummies\" , completed = False ) await course . save () await Course . objects . create ( name = \"Painting for dummies\" , completed = False ) Info To read more about QuerySets (including bulk operations) and available methods visit queries","title":"Initialization"},{"location":"models/#model-methods","text":"","title":"Model methods"},{"location":"models/#load","text":"By default when you query a table without prefetching related models, the ormar will still construct your related models, but populate them only with the pk value. 1 2 3 4 5 6 7 track = await Track . objects . get ( name = 'The Bird' ) track . album . pk # will return malibu album pk (1) track . album . name # will return None # you need to actually load the data first await track . album . load () track . album . name # will return 'Malibu'","title":"load"},{"location":"models/#save","text":"","title":"save"},{"location":"models/#delete","text":"","title":"delete"},{"location":"models/#update","text":"","title":"update"},{"location":"models/#internals","text":"Apart from special parameters defined in the Model during definition (tablename, metadata etc.) the Model provides you with useful internals.","title":"Internals"},{"location":"models/#pydantic-model","text":"All Model classes inherit from pydantic.BaseModel so you can access all normal attributes of pydantic models. For example to list pydantic model fields you can: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) print ( Course . __fields__ ) \"\"\" Will produce: {'id': ModelField(name='id', type=Optional[int], required=False, default=None), 'name': ModelField(name='name', type=Optional[str], required=False, default=None), 'completed': ModelField(name='completed', type=bool, required=False, default=False)} \"\"\" Tip Note how the primary key id field is optional as Integer primary key by default has autoincrement set to True . Info For more options visit official pydantic documentation.","title":"Pydantic Model"},{"location":"models/#sqlalchemy-table","text":"To access auto created sqlalchemy table you can use Model.Meta.table parameter For example to list table columns you can: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) print ( Course . Meta . table . columns ) \"\"\" Will produce: ['courses.id', 'courses.name', 'courses.completed'] \"\"\" Tip You can access table primary key name by Course.Meta.pkname Info For more options visit official sqlalchemy-metadata documentation.","title":"Sqlalchemy Table"},{"location":"models/#fields-definition","text":"To access ormar Fields you can use Model.Meta.model_fields parameter For example to list table model fields you can: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) print ({ x : v . __dict__ for x , v in Course . Meta . model_fields . items ()}) \"\"\" Will produce: {'completed': mappingproxy({'autoincrement': False, 'choices': set(), 'column_type': Boolean(), 'default': False, 'index': False, 'name': 'completed', 'nullable': True, 'primary_key': False, 'pydantic_only': False, 'server_default': None, 'unique': False}), 'id': mappingproxy({'autoincrement': True, 'choices': set(), 'column_type': Integer(), 'default': None, 'ge': None, 'index': False, 'le': None, 'maximum': None, 'minimum': None, 'multiple_of': None, 'name': 'id', 'nullable': False, 'primary_key': True, 'pydantic_only': False, 'server_default': None, 'unique': False}), 'name': mappingproxy({'allow_blank': False, 'autoincrement': False, 'choices': set(), 'column_type': String(length=100), 'curtail_length': None, 'default': None, 'index': False, 'max_length': 100, 'min_length': None, 'name': 'name', 'nullable': False, 'primary_key': False, 'pydantic_only': False, 'regex': None, 'server_default': None, 'strip_whitespace': False, 'unique': False})} \"\"\" Info Note that fields stored on a model are classes not instances . So if you print just model fields you will get: {'id': <class 'ormar.fields.model_fields.Integer'>, 'name': <class 'ormar.fields.model_fields.String'>, 'completed': <class 'ormar.fields.model_fields.Boolean'>}","title":"Fields Definition"},{"location":"queries/","text":"Queries QuerySet Each Model is auto registered with a QuerySet that represents the underlaying query and it's options. Most of the methods are also available through many to many relation interface. Given the Models like this 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Album ( ormar . Model ): class Meta : tablename = \"album\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Track ( ormar . Model ): class Meta : tablename = \"track\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) album : ormar . ForeignKey ( Album ) title : ormar . String ( max_length = 100 ) position : ormar . Integer () we can demonstrate available methods to fetch and save the data into the database. create create(**kwargs): -> Model Creates the model instance, saves it in a database and returns the updates model (with pk populated if not passed and autoincrement is set). The allowed kwargs are Model fields names and proper value types. 1 2 malibu = await Album . objects . create ( name = \"Malibu\" ) await Track . objects . create ( album = malibu , title = \"The Bird\" , position = 1 ) The alternative is a split creation and persistence of the Model . 1 2 malibu = Album ( name = \"Malibu\" ) await malibu . save () Tip Check other Model methods in models get get(**kwargs): -> Model Get's the first row from the db meeting the criteria set by kwargs. If no criteria set it will return the first row in db. Passing a criteria is actually calling filter(**kwargs) method described below. 1 2 3 4 track = await Track . objects . get ( name = 'The Bird' ) # note that above is equivalent to await Track.objects.filter(name='The Bird').get() track2 = track = await Track . objects . get () track == track2 # True since it's the only row in db in our example Warning If no row meets the criteria NoMatch exception is raised. If there are multiple rows meeting the criteria the MultipleMatches exception is raised. get_or_create get_or_create(**kwargs) -> Model Combination of create and get methods. Tries to get a row meeting the criteria and if NoMatch exception is raised it creates a new one with given kwargs. 1 2 3 4 5 album = await Album . objects . get_or_create ( name = 'The Cat' ) # object is created as it does not exist album2 = await Album . objects . get_or_create ( name = 'The Cat' ) assert album == album2 # return True as the same db row is returned Warning Despite being a equivalent row from database the album and album2 in example above are 2 different python objects! Updating one of them will not refresh the second one until you excplicitly load() the fresh data from db. Note Note that if you want to create a new object you either have to pass pk column value or pk column has to be set as autoincrement update update(each: bool = False, **kwargs) -> int QuerySet level update is used to update multiple records with the same value at once. You either have to filter the QuerySet first or provide a each=True flag to update whole table. If you do not provide this flag or a filter a QueryDefinitionError will be raised. Return number of rows updated. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Book ( ormar . Model ): class Meta : tablename = \"books\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) title : ormar . String ( max_length = 200 ) author : ormar . String ( max_length = 100 ) genre : ormar . String ( max_length = 100 , default = 'Fiction' , choices = [ 'Fiction' , 'Adventure' , 'Historic' , 'Fantasy' ]) await Book . objects . create ( title = 'Tom Sawyer' , author = \"Twain, Mark\" , genre = 'Adventure' ) await Book . objects . create ( title = 'War and Peace' , author = \"Tolstoy, Leo\" , genre = 'Fiction' ) await Book . objects . create ( title = 'Anna Karenina' , author = \"Tolstoy, Leo\" , genre = 'Fiction' ) # queryset needs to be filtered before deleting to prevent accidental overwrite # to update whole database table each=True needs to be provided as a safety switch await Book . objects . update ( each = True , genre = 'Fiction' ) all_books = await Book . objects . filter ( genre = 'Fiction' ) . all () assert len ( all_books ) == 3 update_or_create update_or_create(**kwargs) -> Model Updates the model, or in case there is no match in database creates a new one. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Book ( ormar . Model ): class Meta : tablename = \"books\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) title : ormar . String ( max_length = 200 ) author : ormar . String ( max_length = 100 ) genre : ormar . String ( max_length = 100 , default = 'Fiction' , choices = [ 'Fiction' , 'Adventure' , 'Historic' , 'Fantasy' ]) await Book . objects . create ( title = 'Tom Sawyer' , author = \"Twain, Mark\" , genre = 'Adventure' ) await Book . objects . create ( title = 'War and Peace' , author = \"Tolstoy, Leo\" , genre = 'Fiction' ) await Book . objects . create ( title = 'Anna Karenina' , author = \"Tolstoy, Leo\" , genre = 'Fiction' ) # if not exist the instance will be persisted in db vol2 = await Book . objects . update_or_create ( title = \"Volume II\" , author = 'Anonymous' , genre = 'Fiction' ) assert await Book . objects . count () == 1 # if pk or pkname passed in kwargs (like id here) the object will be updated assert await Book . objects . update_or_create ( id = vol2 . id , genre = 'Historic' ) assert await Book . objects . count () == 1 Note Note that if you want to create a new object you either have to pass pk column value or pk column has to be set as autoincrement bulk_create bulk_create(objects: List[\"Model\"]) -> None Allows you to create multiple objects at once. A valid list of Model objects needs to be passed. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class ToDo ( ormar . Model ): class Meta : tablename = \"todos\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) text : ormar . String ( max_length = 500 ) completed : ormar . Boolean ( default = False ) # create multiple instances at once with bulk_create await ToDo . objects . bulk_create ( [ ToDo ( text = \"Buy the groceries.\" ), ToDo ( text = \"Call Mum.\" , completed = True ), ToDo ( text = \"Send invoices.\" , completed = True ), ] ) todoes = await ToDo . objects . all () assert len ( todoes ) == 3 bulk_update bulk_update(objects: List[\"Model\"], columns: List[str] = None) -> None Allows to update multiple instance at once. All Models passed need to have primary key column populated. You can also select which fields to update by passing columns list as a list of string names. 1 2 3 4 5 6 7 8 9 10 11 # continuing the example from bulk_create # update objects for todo in todoes : todo . completed = False # perform update of all objects at once # objects need to have pk column set, otherwise exception is raised await ToDo . objects . bulk_update ( todoes ) completed = await ToDo . objects . filter ( completed = False ) . all () assert len ( completed ) == 3 delete delete(each: bool = False, **kwargs) -> int QuerySet level delete is used to delete multiple records at once. You either have to filter the QuerySet first or provide a each=True flag to delete whole table. If you do not provide this flag or a filter a QueryDefinitionError will be raised. Return number of rows deleted. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Book ( ormar . Model ): class Meta : tablename = \"books\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) title : ormar . String ( max_length = 200 ) author : ormar . String ( max_length = 100 ) genre : ormar . String ( max_length = 100 , default = 'Fiction' , choices = [ 'Fiction' , 'Adventure' , 'Historic' , 'Fantasy' ]) await Book . objects . create ( title = 'Tom Sawyer' , author = \"Twain, Mark\" , genre = 'Adventure' ) await Book . objects . create ( title = 'War and Peace in Space' , author = \"Tolstoy, Leo\" , genre = 'Fantasy' ) await Book . objects . create ( title = 'Anna Karenina' , author = \"Tolstoy, Leo\" , genre = 'Fiction' ) # delete accepts kwargs that will be used in filter # acting in same way as queryset.filter(**kwargs).delete() await Book . objects . delete ( genre = 'Fantasy' ) # delete all fantasy books all_books = await Book . objects . all () assert len ( all_books ) == 2 all all(self, **kwargs) -> List[Optional[\"Model\"]] Returns all rows from a database for given model for set filter options. Passing kwargs is a shortcut and equals to calling filter(**kwrags).all() . If there are no rows meeting the criteria an empty list is returned. 1 2 3 4 5 tracks = await Track . objects . select_related ( \"album\" ) . all ( title = 'Sample' ) # will return a list of all Tracks with title Sample tracks = await Track . objects . all () # will return a list of all Tracks in database filter filter(**kwargs) -> QuerySet Allows you to filter by any Model attribute/field as well as to fetch instances, with a filter across an FK relationship. 1 2 3 4 5 track = Track . objects . filter ( name = \"The Bird\" ) . get () # will return a track with name equal to 'The Bird' tracks = Track . objects . filter ( album__name = \"Fantasies\" ) . all () # will return all tracks where the columns album name = 'Fantasies' You can use special filter suffix to change the filter operands: exact - like album__name__exact='Malibu' (exact match) iexact - like album__name__iexact='malibu' (exact match case insensitive) contains - like album__name__conatins='Mal' (sql like) icontains - like album__name__icontains='mal' (sql like case insensitive) in - like album__name__in=['Malibu', 'Barclay'] (sql in) gt - like position__gt=3 (sql >) gte - like position__gte=3 (sql >=) lt - like position__lt=3 (sql <) lte - like position__lte=3 (sql <=) startswith - like album__name__startswith='Mal' (exact start match) istartswith - like album__name__istartswith='mal' (exact start match case insensitive) endswith - like album__name__endswith='ibu' (exact end match) iendswith - like album__name__iendswith='IBU' (exact end match case insensitive) Note All methods that do not return the rows explicitly returns a QueySet instance so you can chain them together So operations like filter() , select_related() , limit() and offset() etc. can be chained. Something like Track.object.select_related(\"album\").filter(album__name=\"Malibu\").offset(1).limit(1).all() exclude exclude(**kwargs) -> QuerySet Works exactly the same as filter and all modifiers (suffixes) are the same, but returns a not condition. So if you use filter(name='John') which equals to where name = 'John' in SQL, the exclude(name='John') equals to where name <> 'John' Note that all conditions are joined so if you pass multiple values it becomes a union of conditions. exclude(name='John', age>=35) will become where not (name='John' and age>=35) 1 2 notes = await Track . objects . exclude ( position_gt = 3 ) . all () # returns all tracks with position < 3 select_related select_related(related: Union[List, str]) -> QuerySet Allows to prefetch related models. To fetch related model use ForeignKey names. To chain related Models relation use double underscore. 1 2 album = await Album . objects . select_related ( \"tracks\" ) . all () # will return album will all columns tracks You can provide a string or a list of strings 1 2 3 4 classes = await SchoolClass . objects . select_related ( [ \"teachers__category\" , \"students\" ]) . all () # will return classes with teachers and teachers categories # as well as classes students Exactly the same behavior is for Many2Many fields, where you put the names of Many2Many fields and the final Models are fetched for you. Warning If you set ForeignKey field as not nullable (so required) during all queries the not nullable Models will be auto prefetched, even if you do not include them in select_related. Note All methods that do not return the rows explicitly returns a QueySet instance so you can chain them together So operations like filter() , select_related() , limit() and offset() etc. can be chained. Something like Track.object.select_related(\"album\").filter(album__name=\"Malibu\").offset(1).limit(1).all() limit limit(limit_count: int) -> QuerySet You can limit the results to desired number of rows. 1 2 tracks = await Track . objects . limit ( 1 ) . all () # will return just one Track Note All methods that do not return the rows explicitly returns a QueySet instance so you can chain them together So operations like filter() , select_related() , limit() and offset() etc. can be chained. Something like Track.object.select_related(\"album\").filter(album__name=\"Malibu\").offset(1).limit(1).all() offset offset(offset: int) -> QuerySet You can also offset the results by desired number of rows. 1 2 tracks = await Track . objects . offset ( 1 ) . limit ( 1 ) . all () # will return just one Track, but this time the second one Note All methods that do not return the rows explicitly returns a QueySet instance so you can chain them together So operations like filter() , select_related() , limit() and offset() etc. can be chained. Something like Track.object.select_related(\"album\").filter(album__name=\"Malibu\").offset(1).limit(1).all() count count() -> int Returns number of rows matching the given criteria (applied with filter and exclude ) 1 2 # returns count of rows in db no_of_books = await Book . objects . count () exists exists() -> bool Returns a bool value to confirm if there are rows matching the given criteria (applied with filter and exclude ) 1 2 # returns a boolean value if given row exists has_sample = await Book . objects . filter ( title = 'Sample' ) . exists () fields fields(columns: Union[List, str]) -> QuerySet With fields() you can select subset of model columns to limit the data load. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 import databases import sqlalchemy import ormar from tests.settings import DATABASE_URL database = databases . Database ( DATABASE_URL , force_rollback = True ) metadata = sqlalchemy . MetaData () class Company ( ormar . Model ): class Meta : tablename = \"companies\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) founded : ormar . Integer ( nullable = True ) class Car ( ormar . Model ): class Meta : tablename = \"cars\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) manufacturer : ormar . ForeignKey ( Company ) name : ormar . String ( max_length = 100 ) year : ormar . Integer ( nullable = True ) gearbox_type : ormar . String ( max_length = 20 , nullable = True ) gears : ormar . Integer ( nullable = True ) aircon_type : ormar . String ( max_length = 20 , nullable = True ) # build some sample data toyota = await Company . objects . create ( name = \"Toyota\" , founded = 1937 ) await Car . objects . create ( manufacturer = toyota , name = \"Corolla\" , year = 2020 , gearbox_type = 'Manual' , gears = 5 , aircon_type = 'Manual' ) await Car . objects . create ( manufacturer = toyota , name = \"Yaris\" , year = 2019 , gearbox_type = 'Manual' , gears = 5 , aircon_type = 'Manual' ) await Car . objects . create ( manufacturer = toyota , name = \"Supreme\" , year = 2020 , gearbox_type = 'Auto' , gears = 6 , aircon_type = 'Auto' ) # select manufacturer but only name - to include related models use notation {model_name}__{column} all_cars = await Car . objects . select_related ( 'manufacturer' ) . fields ([ 'id' , 'name' , 'company__name' ]) . all () for car in all_cars : # excluded columns will yield None assert all ( getattr ( car , x ) is None for x in [ 'year' , 'gearbox_type' , 'gears' , 'aircon_type' ]) # included column on related models will be available, pk column is always included # even if you do not include it in fields list assert car . manufacturer . name == 'Toyota' # also in the nested related models - you cannot exclude pk - it's always auto added assert car . manufacturer . founded is None # fields() can be called several times, building up the columns to select # models selected in select_related but with no columns in fields list implies all fields all_cars = await Car . objects . select_related ( 'manufacturer' ) . fields ( 'id' ) . fields ( [ 'name' ]) . all () # all fiels from company model are selected assert all_cars [ 0 ] . manufacturer . name == 'Toyota' assert all_cars [ 0 ] . manufacturer . founded == 1937 # cannot exclude mandatory model columns - company__name in this example await Car . objects . select_related ( 'manufacturer' ) . fields ([ 'id' , 'name' , 'company__founded' ]) . all () # will raise pydantic ValidationError as company.name is required Warning Mandatory fields cannot be excluded as it will raise ValidationError , to exclude a field it has to be nullable. Tip Pk column cannot be excluded - it's always auto added even if not explicitly included. Note All methods that do not return the rows explicitly returns a QueySet instance so you can chain them together So operations like filter() , select_related() , limit() and offset() etc. can be chained. Something like Track.object.select_related(\"album\").filter(album__name=\"Malibu\").offset(1).limit(1).all()","title":"Queries"},{"location":"queries/#queries","text":"","title":"Queries"},{"location":"queries/#queryset","text":"Each Model is auto registered with a QuerySet that represents the underlaying query and it's options. Most of the methods are also available through many to many relation interface. Given the Models like this 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Album ( ormar . Model ): class Meta : tablename = \"album\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Track ( ormar . Model ): class Meta : tablename = \"track\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) album : ormar . ForeignKey ( Album ) title : ormar . String ( max_length = 100 ) position : ormar . Integer () we can demonstrate available methods to fetch and save the data into the database.","title":"QuerySet"},{"location":"queries/#create","text":"create(**kwargs): -> Model Creates the model instance, saves it in a database and returns the updates model (with pk populated if not passed and autoincrement is set). The allowed kwargs are Model fields names and proper value types. 1 2 malibu = await Album . objects . create ( name = \"Malibu\" ) await Track . objects . create ( album = malibu , title = \"The Bird\" , position = 1 ) The alternative is a split creation and persistence of the Model . 1 2 malibu = Album ( name = \"Malibu\" ) await malibu . save () Tip Check other Model methods in models","title":"create"},{"location":"queries/#get","text":"get(**kwargs): -> Model Get's the first row from the db meeting the criteria set by kwargs. If no criteria set it will return the first row in db. Passing a criteria is actually calling filter(**kwargs) method described below. 1 2 3 4 track = await Track . objects . get ( name = 'The Bird' ) # note that above is equivalent to await Track.objects.filter(name='The Bird').get() track2 = track = await Track . objects . get () track == track2 # True since it's the only row in db in our example Warning If no row meets the criteria NoMatch exception is raised. If there are multiple rows meeting the criteria the MultipleMatches exception is raised.","title":"get"},{"location":"queries/#get_or_create","text":"get_or_create(**kwargs) -> Model Combination of create and get methods. Tries to get a row meeting the criteria and if NoMatch exception is raised it creates a new one with given kwargs. 1 2 3 4 5 album = await Album . objects . get_or_create ( name = 'The Cat' ) # object is created as it does not exist album2 = await Album . objects . get_or_create ( name = 'The Cat' ) assert album == album2 # return True as the same db row is returned Warning Despite being a equivalent row from database the album and album2 in example above are 2 different python objects! Updating one of them will not refresh the second one until you excplicitly load() the fresh data from db. Note Note that if you want to create a new object you either have to pass pk column value or pk column has to be set as autoincrement","title":"get_or_create"},{"location":"queries/#update","text":"update(each: bool = False, **kwargs) -> int QuerySet level update is used to update multiple records with the same value at once. You either have to filter the QuerySet first or provide a each=True flag to update whole table. If you do not provide this flag or a filter a QueryDefinitionError will be raised. Return number of rows updated. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Book ( ormar . Model ): class Meta : tablename = \"books\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) title : ormar . String ( max_length = 200 ) author : ormar . String ( max_length = 100 ) genre : ormar . String ( max_length = 100 , default = 'Fiction' , choices = [ 'Fiction' , 'Adventure' , 'Historic' , 'Fantasy' ]) await Book . objects . create ( title = 'Tom Sawyer' , author = \"Twain, Mark\" , genre = 'Adventure' ) await Book . objects . create ( title = 'War and Peace' , author = \"Tolstoy, Leo\" , genre = 'Fiction' ) await Book . objects . create ( title = 'Anna Karenina' , author = \"Tolstoy, Leo\" , genre = 'Fiction' ) # queryset needs to be filtered before deleting to prevent accidental overwrite # to update whole database table each=True needs to be provided as a safety switch await Book . objects . update ( each = True , genre = 'Fiction' ) all_books = await Book . objects . filter ( genre = 'Fiction' ) . all () assert len ( all_books ) == 3","title":"update"},{"location":"queries/#update_or_create","text":"update_or_create(**kwargs) -> Model Updates the model, or in case there is no match in database creates a new one. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Book ( ormar . Model ): class Meta : tablename = \"books\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) title : ormar . String ( max_length = 200 ) author : ormar . String ( max_length = 100 ) genre : ormar . String ( max_length = 100 , default = 'Fiction' , choices = [ 'Fiction' , 'Adventure' , 'Historic' , 'Fantasy' ]) await Book . objects . create ( title = 'Tom Sawyer' , author = \"Twain, Mark\" , genre = 'Adventure' ) await Book . objects . create ( title = 'War and Peace' , author = \"Tolstoy, Leo\" , genre = 'Fiction' ) await Book . objects . create ( title = 'Anna Karenina' , author = \"Tolstoy, Leo\" , genre = 'Fiction' ) # if not exist the instance will be persisted in db vol2 = await Book . objects . update_or_create ( title = \"Volume II\" , author = 'Anonymous' , genre = 'Fiction' ) assert await Book . objects . count () == 1 # if pk or pkname passed in kwargs (like id here) the object will be updated assert await Book . objects . update_or_create ( id = vol2 . id , genre = 'Historic' ) assert await Book . objects . count () == 1 Note Note that if you want to create a new object you either have to pass pk column value or pk column has to be set as autoincrement","title":"update_or_create"},{"location":"queries/#bulk_create","text":"bulk_create(objects: List[\"Model\"]) -> None Allows you to create multiple objects at once. A valid list of Model objects needs to be passed. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class ToDo ( ormar . Model ): class Meta : tablename = \"todos\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) text : ormar . String ( max_length = 500 ) completed : ormar . Boolean ( default = False ) # create multiple instances at once with bulk_create await ToDo . objects . bulk_create ( [ ToDo ( text = \"Buy the groceries.\" ), ToDo ( text = \"Call Mum.\" , completed = True ), ToDo ( text = \"Send invoices.\" , completed = True ), ] ) todoes = await ToDo . objects . all () assert len ( todoes ) == 3","title":"bulk_create"},{"location":"queries/#bulk_update","text":"bulk_update(objects: List[\"Model\"], columns: List[str] = None) -> None Allows to update multiple instance at once. All Models passed need to have primary key column populated. You can also select which fields to update by passing columns list as a list of string names. 1 2 3 4 5 6 7 8 9 10 11 # continuing the example from bulk_create # update objects for todo in todoes : todo . completed = False # perform update of all objects at once # objects need to have pk column set, otherwise exception is raised await ToDo . objects . bulk_update ( todoes ) completed = await ToDo . objects . filter ( completed = False ) . all () assert len ( completed ) == 3","title":"bulk_update"},{"location":"queries/#delete","text":"delete(each: bool = False, **kwargs) -> int QuerySet level delete is used to delete multiple records at once. You either have to filter the QuerySet first or provide a each=True flag to delete whole table. If you do not provide this flag or a filter a QueryDefinitionError will be raised. Return number of rows deleted. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Book ( ormar . Model ): class Meta : tablename = \"books\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) title : ormar . String ( max_length = 200 ) author : ormar . String ( max_length = 100 ) genre : ormar . String ( max_length = 100 , default = 'Fiction' , choices = [ 'Fiction' , 'Adventure' , 'Historic' , 'Fantasy' ]) await Book . objects . create ( title = 'Tom Sawyer' , author = \"Twain, Mark\" , genre = 'Adventure' ) await Book . objects . create ( title = 'War and Peace in Space' , author = \"Tolstoy, Leo\" , genre = 'Fantasy' ) await Book . objects . create ( title = 'Anna Karenina' , author = \"Tolstoy, Leo\" , genre = 'Fiction' ) # delete accepts kwargs that will be used in filter # acting in same way as queryset.filter(**kwargs).delete() await Book . objects . delete ( genre = 'Fantasy' ) # delete all fantasy books all_books = await Book . objects . all () assert len ( all_books ) == 2","title":"delete"},{"location":"queries/#all","text":"all(self, **kwargs) -> List[Optional[\"Model\"]] Returns all rows from a database for given model for set filter options. Passing kwargs is a shortcut and equals to calling filter(**kwrags).all() . If there are no rows meeting the criteria an empty list is returned. 1 2 3 4 5 tracks = await Track . objects . select_related ( \"album\" ) . all ( title = 'Sample' ) # will return a list of all Tracks with title Sample tracks = await Track . objects . all () # will return a list of all Tracks in database","title":"all"},{"location":"queries/#filter","text":"filter(**kwargs) -> QuerySet Allows you to filter by any Model attribute/field as well as to fetch instances, with a filter across an FK relationship. 1 2 3 4 5 track = Track . objects . filter ( name = \"The Bird\" ) . get () # will return a track with name equal to 'The Bird' tracks = Track . objects . filter ( album__name = \"Fantasies\" ) . all () # will return all tracks where the columns album name = 'Fantasies' You can use special filter suffix to change the filter operands: exact - like album__name__exact='Malibu' (exact match) iexact - like album__name__iexact='malibu' (exact match case insensitive) contains - like album__name__conatins='Mal' (sql like) icontains - like album__name__icontains='mal' (sql like case insensitive) in - like album__name__in=['Malibu', 'Barclay'] (sql in) gt - like position__gt=3 (sql >) gte - like position__gte=3 (sql >=) lt - like position__lt=3 (sql <) lte - like position__lte=3 (sql <=) startswith - like album__name__startswith='Mal' (exact start match) istartswith - like album__name__istartswith='mal' (exact start match case insensitive) endswith - like album__name__endswith='ibu' (exact end match) iendswith - like album__name__iendswith='IBU' (exact end match case insensitive) Note All methods that do not return the rows explicitly returns a QueySet instance so you can chain them together So operations like filter() , select_related() , limit() and offset() etc. can be chained. Something like Track.object.select_related(\"album\").filter(album__name=\"Malibu\").offset(1).limit(1).all()","title":"filter"},{"location":"queries/#exclude","text":"exclude(**kwargs) -> QuerySet Works exactly the same as filter and all modifiers (suffixes) are the same, but returns a not condition. So if you use filter(name='John') which equals to where name = 'John' in SQL, the exclude(name='John') equals to where name <> 'John' Note that all conditions are joined so if you pass multiple values it becomes a union of conditions. exclude(name='John', age>=35) will become where not (name='John' and age>=35) 1 2 notes = await Track . objects . exclude ( position_gt = 3 ) . all () # returns all tracks with position < 3","title":"exclude"},{"location":"queries/#select_related","text":"select_related(related: Union[List, str]) -> QuerySet Allows to prefetch related models. To fetch related model use ForeignKey names. To chain related Models relation use double underscore. 1 2 album = await Album . objects . select_related ( \"tracks\" ) . all () # will return album will all columns tracks You can provide a string or a list of strings 1 2 3 4 classes = await SchoolClass . objects . select_related ( [ \"teachers__category\" , \"students\" ]) . all () # will return classes with teachers and teachers categories # as well as classes students Exactly the same behavior is for Many2Many fields, where you put the names of Many2Many fields and the final Models are fetched for you. Warning If you set ForeignKey field as not nullable (so required) during all queries the not nullable Models will be auto prefetched, even if you do not include them in select_related. Note All methods that do not return the rows explicitly returns a QueySet instance so you can chain them together So operations like filter() , select_related() , limit() and offset() etc. can be chained. Something like Track.object.select_related(\"album\").filter(album__name=\"Malibu\").offset(1).limit(1).all()","title":"select_related"},{"location":"queries/#limit","text":"limit(limit_count: int) -> QuerySet You can limit the results to desired number of rows. 1 2 tracks = await Track . objects . limit ( 1 ) . all () # will return just one Track Note All methods that do not return the rows explicitly returns a QueySet instance so you can chain them together So operations like filter() , select_related() , limit() and offset() etc. can be chained. Something like Track.object.select_related(\"album\").filter(album__name=\"Malibu\").offset(1).limit(1).all()","title":"limit"},{"location":"queries/#offset","text":"offset(offset: int) -> QuerySet You can also offset the results by desired number of rows. 1 2 tracks = await Track . objects . offset ( 1 ) . limit ( 1 ) . all () # will return just one Track, but this time the second one Note All methods that do not return the rows explicitly returns a QueySet instance so you can chain them together So operations like filter() , select_related() , limit() and offset() etc. can be chained. Something like Track.object.select_related(\"album\").filter(album__name=\"Malibu\").offset(1).limit(1).all()","title":"offset"},{"location":"queries/#count","text":"count() -> int Returns number of rows matching the given criteria (applied with filter and exclude ) 1 2 # returns count of rows in db no_of_books = await Book . objects . count ()","title":"count"},{"location":"queries/#exists","text":"exists() -> bool Returns a bool value to confirm if there are rows matching the given criteria (applied with filter and exclude ) 1 2 # returns a boolean value if given row exists has_sample = await Book . objects . filter ( title = 'Sample' ) . exists ()","title":"exists"},{"location":"queries/#fields","text":"fields(columns: Union[List, str]) -> QuerySet With fields() you can select subset of model columns to limit the data load. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 import databases import sqlalchemy import ormar from tests.settings import DATABASE_URL database = databases . Database ( DATABASE_URL , force_rollback = True ) metadata = sqlalchemy . MetaData () class Company ( ormar . Model ): class Meta : tablename = \"companies\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) founded : ormar . Integer ( nullable = True ) class Car ( ormar . Model ): class Meta : tablename = \"cars\" metadata = metadata database = database id : ormar . Integer ( primary_key = True ) manufacturer : ormar . ForeignKey ( Company ) name : ormar . String ( max_length = 100 ) year : ormar . Integer ( nullable = True ) gearbox_type : ormar . String ( max_length = 20 , nullable = True ) gears : ormar . Integer ( nullable = True ) aircon_type : ormar . String ( max_length = 20 , nullable = True ) # build some sample data toyota = await Company . objects . create ( name = \"Toyota\" , founded = 1937 ) await Car . objects . create ( manufacturer = toyota , name = \"Corolla\" , year = 2020 , gearbox_type = 'Manual' , gears = 5 , aircon_type = 'Manual' ) await Car . objects . create ( manufacturer = toyota , name = \"Yaris\" , year = 2019 , gearbox_type = 'Manual' , gears = 5 , aircon_type = 'Manual' ) await Car . objects . create ( manufacturer = toyota , name = \"Supreme\" , year = 2020 , gearbox_type = 'Auto' , gears = 6 , aircon_type = 'Auto' ) # select manufacturer but only name - to include related models use notation {model_name}__{column} all_cars = await Car . objects . select_related ( 'manufacturer' ) . fields ([ 'id' , 'name' , 'company__name' ]) . all () for car in all_cars : # excluded columns will yield None assert all ( getattr ( car , x ) is None for x in [ 'year' , 'gearbox_type' , 'gears' , 'aircon_type' ]) # included column on related models will be available, pk column is always included # even if you do not include it in fields list assert car . manufacturer . name == 'Toyota' # also in the nested related models - you cannot exclude pk - it's always auto added assert car . manufacturer . founded is None # fields() can be called several times, building up the columns to select # models selected in select_related but with no columns in fields list implies all fields all_cars = await Car . objects . select_related ( 'manufacturer' ) . fields ( 'id' ) . fields ( [ 'name' ]) . all () # all fiels from company model are selected assert all_cars [ 0 ] . manufacturer . name == 'Toyota' assert all_cars [ 0 ] . manufacturer . founded == 1937 # cannot exclude mandatory model columns - company__name in this example await Car . objects . select_related ( 'manufacturer' ) . fields ([ 'id' , 'name' , 'company__founded' ]) . all () # will raise pydantic ValidationError as company.name is required Warning Mandatory fields cannot be excluded as it will raise ValidationError , to exclude a field it has to be nullable. Tip Pk column cannot be excluded - it's always auto added even if not explicitly included. Note All methods that do not return the rows explicitly returns a QueySet instance so you can chain them together So operations like filter() , select_related() , limit() and offset() etc. can be chained. Something like Track.object.select_related(\"album\").filter(album__name=\"Malibu\").offset(1).limit(1).all()","title":"fields"},{"location":"relations/","text":"Relations Defining a relationship ForeignKey ForeignKey(to, related_name=None) has required parameters to that takes target Model class. Sqlalchemy column and Type are automatically taken from target Model . Sqlalchemy column: class of a target Model primary key column Type (used for pydantic): type of a target Model Defining Models To define a relation add ForeignKey field that points to related Model . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department ) Reverse Relation ForeignKey fields are automatically registering reverse side of the relation. By default it's child (source) Model name + s, like courses in snippet below: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department ) department = Department ( name = 'Science' ) course = Course ( name = 'Math' , completed = False , department = department ) print ( department . courses [ 0 ]) # Will produce: # Course(id=None, # name='Math', # completed=False, # department=Department(id=None, name='Science')) related_name But you can overwrite this name by providing related_name parameter like below: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department , related_name = \"my_courses\" ) department = Department ( name = 'Science' ) course = Course ( name = 'Math' , completed = False , department = department ) print ( department . my_courses [ 0 ]) # Will produce: # Course(id=None, # name='Math', # completed=False, # department=Department(id=None, name='Science')) Tip The reverse relation on access returns list of wekref.proxy to avoid circular references. Relation Setup You have several ways to set-up a relationship connection. Model instance The most obvious one is to pass a related Model instance to the constructor. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department ) department = Department ( name = 'Science' ) # set up a relation with actual Model instance course = Course ( name = 'Math' , completed = False , department = department ) # set up relation with only related model pk value course2 = Course ( name = 'Math II' , completed = False , department = department . pk ) # set up a relation with dictionary corresponding to related model course3 = Course ( name = 'Math III' , completed = False , department = department . dict ()) # explicitly set up None course4 = Course ( name = 'Math III' , completed = False , department = None ) Primary key value You can setup the relation also with just the pk column value of the related model. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department ) department = Department ( name = 'Science' ) # set up a relation with actual Model instance course = Course ( name = 'Math' , completed = False , department = department ) # set up relation with only related model pk value course2 = Course ( name = 'Math II' , completed = False , department = department . pk ) # set up a relation with dictionary corresponding to related model course3 = Course ( name = 'Math III' , completed = False , department = department . dict ()) # explicitly set up None course4 = Course ( name = 'Math III' , completed = False , department = None ) Dictionary Next option is with a dictionary of key-values of the related model. You can build the dictionary yourself or get it from existing model with dict() method. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department ) department = Department ( name = 'Science' ) # set up a relation with actual Model instance course = Course ( name = 'Math' , completed = False , department = department ) # set up relation with only related model pk value course2 = Course ( name = 'Math II' , completed = False , department = department . pk ) # set up a relation with dictionary corresponding to related model course3 = Course ( name = 'Math III' , completed = False , department = department . dict ()) # explicitly set up None course4 = Course ( name = 'Math III' , completed = False , department = None ) None Finally you can explicitly set it to None (default behavior if no value passed). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department ) department = Department ( name = 'Science' ) # set up a relation with actual Model instance course = Course ( name = 'Math' , completed = False , department = department ) # set up relation with only related model pk value course2 = Course ( name = 'Math II' , completed = False , department = department . pk ) # set up a relation with dictionary corresponding to related model course3 = Course ( name = 'Math III' , completed = False , department = department . dict ()) # explicitly set up None course4 = Course ( name = 'Math III' , completed = False , department = None ) Warning In all not None cases the primary key value for related model has to exist in database . Otherwise an IntegrityError will be raised by your database driver library. Many2Many Many2Many(to, through) has required parameters to and through that takes target and relation Model classes. Sqlalchemy column and Type are automatically taken from target Model . Sqlalchemy column: class of a target Model primary key column Type (used for pydantic): type of a target Model Defining Models : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Author ( ormar . Model ): class Meta : tablename = \"authors\" database = database metadata = metadata id : ormar . Integer ( primary_key = True ) first_name : ormar . String ( max_length = 80 ) last_name : ormar . String ( max_length = 80 ) class Category ( ormar . Model ): class Meta : tablename = \"categories\" database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 40 ) class PostCategory ( ormar . Model ): class Meta : tablename = \"posts_categories\" database = database metadata = metadata # If there are no additional columns id will be created automatically as Integer class Post ( ormar . Model ): class Meta : tablename = \"posts\" database = database metadata = metadata id : ormar . Integer ( primary_key = True ) title : ormar . String ( max_length = 200 ) categories : ormar . ManyToMany ( Category , through = PostCategory ) author : ormar . ForeignKey ( Author ) Create sample data: 1 2 3 guido = await Author . objects . create ( first_name = \"Guido\" , last_name = \"Van Rossum\" ) post = await Post . objects . create ( title = \"Hello, M2M\" , author = guido ) news = await Category . objects . create ( name = \"News\" ) Adding related models 1 2 3 4 # Add a category to a post. await post . categories . add ( news ) # or from the other end: await news . posts . add ( post ) Warning In all not None cases the primary key value for related model has to exist in database . Otherwise an IntegrityError will be raised by your database driver library. Creating new related Model instances 1 2 3 4 # Creating columns object from instance: await post . categories . create ( name = \"Tips\" ) assert len ( await post . categories . all ()) == 2 # newly created instance already have relation persisted in the database Note Note that when accessing QuerySet API methods through Many2Many relation you don't need to use objects attribute like in normal queries. To learn more about available QuerySet methods visit queries Removing related models 1 2 3 4 # Removal of the relationship by one await news . posts . remove ( post ) # or all at once await news . posts . clear () All other queryset methods When access directly the related Many2Many field returns the list of related models. But at the same time it exposes full QuerySet API, so you can filter, create, select related etc. 1 2 3 4 5 6 7 8 9 10 11 # Many to many relation exposes a list of columns models # and an API of the Queryset: assert news == await post . categories . get ( name = \"News\" ) # with all Queryset methods - filtering, selecting columns, counting etc. await news . posts . filter ( title__contains = \"M2M\" ) . all () await Category . objects . filter ( posts__author = guido ) . get () # columns models of many to many relation can be prefetched news_posts = await news . posts . select_related ( \"author\" ) . all () assert news_posts [ 0 ] . author == guido Tip To learn more about available QuerySet methods visit queries","title":"Relations"},{"location":"relations/#relations","text":"","title":"Relations"},{"location":"relations/#defining-a-relationship","text":"","title":"Defining a relationship"},{"location":"relations/#foreignkey","text":"ForeignKey(to, related_name=None) has required parameters to that takes target Model class. Sqlalchemy column and Type are automatically taken from target Model . Sqlalchemy column: class of a target Model primary key column Type (used for pydantic): type of a target Model","title":"ForeignKey"},{"location":"relations/#defining-models","text":"To define a relation add ForeignKey field that points to related Model . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department )","title":"Defining Models"},{"location":"relations/#reverse-relation","text":"ForeignKey fields are automatically registering reverse side of the relation. By default it's child (source) Model name + s, like courses in snippet below: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department ) department = Department ( name = 'Science' ) course = Course ( name = 'Math' , completed = False , department = department ) print ( department . courses [ 0 ]) # Will produce: # Course(id=None, # name='Math', # completed=False, # department=Department(id=None, name='Science'))","title":"Reverse Relation"},{"location":"relations/#related_name","text":"But you can overwrite this name by providing related_name parameter like below: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department , related_name = \"my_courses\" ) department = Department ( name = 'Science' ) course = Course ( name = 'Math' , completed = False , department = department ) print ( department . my_courses [ 0 ]) # Will produce: # Course(id=None, # name='Math', # completed=False, # department=Department(id=None, name='Science')) Tip The reverse relation on access returns list of wekref.proxy to avoid circular references.","title":"related_name"},{"location":"relations/#relation-setup","text":"You have several ways to set-up a relationship connection.","title":"Relation Setup"},{"location":"relations/#model-instance","text":"The most obvious one is to pass a related Model instance to the constructor. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department ) department = Department ( name = 'Science' ) # set up a relation with actual Model instance course = Course ( name = 'Math' , completed = False , department = department ) # set up relation with only related model pk value course2 = Course ( name = 'Math II' , completed = False , department = department . pk ) # set up a relation with dictionary corresponding to related model course3 = Course ( name = 'Math III' , completed = False , department = department . dict ()) # explicitly set up None course4 = Course ( name = 'Math III' , completed = False , department = None )","title":"Model instance"},{"location":"relations/#primary-key-value","text":"You can setup the relation also with just the pk column value of the related model. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department ) department = Department ( name = 'Science' ) # set up a relation with actual Model instance course = Course ( name = 'Math' , completed = False , department = department ) # set up relation with only related model pk value course2 = Course ( name = 'Math II' , completed = False , department = department . pk ) # set up a relation with dictionary corresponding to related model course3 = Course ( name = 'Math III' , completed = False , department = department . dict ()) # explicitly set up None course4 = Course ( name = 'Math III' , completed = False , department = None )","title":"Primary key value"},{"location":"relations/#dictionary","text":"Next option is with a dictionary of key-values of the related model. You can build the dictionary yourself or get it from existing model with dict() method. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department ) department = Department ( name = 'Science' ) # set up a relation with actual Model instance course = Course ( name = 'Math' , completed = False , department = department ) # set up relation with only related model pk value course2 = Course ( name = 'Math II' , completed = False , department = department . pk ) # set up a relation with dictionary corresponding to related model course3 = Course ( name = 'Math III' , completed = False , department = department . dict ()) # explicitly set up None course4 = Course ( name = 'Math III' , completed = False , department = None )","title":"Dictionary"},{"location":"relations/#none","text":"Finally you can explicitly set it to None (default behavior if no value passed). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import databases import sqlalchemy import ormar database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Department ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) class Course ( ormar . Model ): class Meta : database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 100 ) completed : ormar . Boolean ( default = False ) department : ormar . ForeignKey ( Department ) department = Department ( name = 'Science' ) # set up a relation with actual Model instance course = Course ( name = 'Math' , completed = False , department = department ) # set up relation with only related model pk value course2 = Course ( name = 'Math II' , completed = False , department = department . pk ) # set up a relation with dictionary corresponding to related model course3 = Course ( name = 'Math III' , completed = False , department = department . dict ()) # explicitly set up None course4 = Course ( name = 'Math III' , completed = False , department = None ) Warning In all not None cases the primary key value for related model has to exist in database . Otherwise an IntegrityError will be raised by your database driver library.","title":"None"},{"location":"relations/#many2many","text":"Many2Many(to, through) has required parameters to and through that takes target and relation Model classes. Sqlalchemy column and Type are automatically taken from target Model . Sqlalchemy column: class of a target Model primary key column Type (used for pydantic): type of a target Model","title":"Many2Many"},{"location":"relations/#defining-models_1","text":"1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 import databases import ormar import sqlalchemy database = databases . Database ( \"sqlite:///db.sqlite\" ) metadata = sqlalchemy . MetaData () class Author ( ormar . Model ): class Meta : tablename = \"authors\" database = database metadata = metadata id : ormar . Integer ( primary_key = True ) first_name : ormar . String ( max_length = 80 ) last_name : ormar . String ( max_length = 80 ) class Category ( ormar . Model ): class Meta : tablename = \"categories\" database = database metadata = metadata id : ormar . Integer ( primary_key = True ) name : ormar . String ( max_length = 40 ) class PostCategory ( ormar . Model ): class Meta : tablename = \"posts_categories\" database = database metadata = metadata # If there are no additional columns id will be created automatically as Integer class Post ( ormar . Model ): class Meta : tablename = \"posts\" database = database metadata = metadata id : ormar . Integer ( primary_key = True ) title : ormar . String ( max_length = 200 ) categories : ormar . ManyToMany ( Category , through = PostCategory ) author : ormar . ForeignKey ( Author ) Create sample data: 1 2 3 guido = await Author . objects . create ( first_name = \"Guido\" , last_name = \"Van Rossum\" ) post = await Post . objects . create ( title = \"Hello, M2M\" , author = guido ) news = await Category . objects . create ( name = \"News\" )","title":"Defining Models:"},{"location":"relations/#adding-related-models","text":"1 2 3 4 # Add a category to a post. await post . categories . add ( news ) # or from the other end: await news . posts . add ( post ) Warning In all not None cases the primary key value for related model has to exist in database . Otherwise an IntegrityError will be raised by your database driver library.","title":"Adding related models"},{"location":"relations/#creating-new-related-model-instances","text":"1 2 3 4 # Creating columns object from instance: await post . categories . create ( name = \"Tips\" ) assert len ( await post . categories . all ()) == 2 # newly created instance already have relation persisted in the database Note Note that when accessing QuerySet API methods through Many2Many relation you don't need to use objects attribute like in normal queries. To learn more about available QuerySet methods visit queries","title":"Creating new related Model instances"},{"location":"relations/#removing-related-models","text":"1 2 3 4 # Removal of the relationship by one await news . posts . remove ( post ) # or all at once await news . posts . clear ()","title":"Removing related models"},{"location":"relations/#all-other-queryset-methods","text":"When access directly the related Many2Many field returns the list of related models. But at the same time it exposes full QuerySet API, so you can filter, create, select related etc. 1 2 3 4 5 6 7 8 9 10 11 # Many to many relation exposes a list of columns models # and an API of the Queryset: assert news == await post . categories . get ( name = \"News\" ) # with all Queryset methods - filtering, selecting columns, counting etc. await news . posts . filter ( title__contains = \"M2M\" ) . all () await Category . objects . filter ( posts__author = guido ) . get () # columns models of many to many relation can be prefetched news_posts = await news . posts . select_related ( \"author\" ) . all () assert news_posts [ 0 ] . author == guido Tip To learn more about available QuerySet methods visit queries","title":"All other queryset methods"},{"location":"testing/","text":"","title":"Testing"}]} |