diff --git a/.coverage b/.coverage index d661345..07f5594 100644 Binary files a/.coverage and b/.coverage differ diff --git a/.gitignore b/.gitignore index a9b621f..22d9e75 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ p38venv .pytest_cache *.pyc *.log -test.db \ No newline at end of file +test.db +dist \ No newline at end of file diff --git a/README.md b/README.md index 3186786..d72c80b 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ Coverage - -CodeFactor + +CodeFactor Codacy @@ -35,22 +35,22 @@ The encode package was too simple (i.e. no ability to join two times to the same ```python import databases -import orm +import ormar import sqlalchemy database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Note(orm.Model): +class Note(ormar.Model): __tablename__ = "notes" __database__ = database __metadata__ = metadata # primary keys of type int by dafault are set to autoincrement - id = orm.Integer(primary_key=True) - text = orm.String(length=100) - completed = orm.Boolean(default=False) + id = ormar.Integer(primary_key=True) + text = ormar.String(length=100) + completed = ormar.Boolean(default=False) # Create the database engine = sqlalchemy.create_engine(str(database.url)) @@ -88,31 +88,31 @@ ORM supports loading and filtering across foreign keys... ```python import databases -import orm +import ormar import sqlalchemy database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Album(orm.Model): +class Album(ormar.Model): __tablename__ = "album" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Track(orm.Model): +class Track(ormar.Model): __tablename__ = "track" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - album = orm.ForeignKey(Album) - title = orm.String(length=100) - position = orm.Integer() + id = ormar.Integer(primary_key=True) + album = ormar.ForeignKey(Album) + title = ormar.String(length=100) + position = ormar.Integer() # Create some records to work with. diff --git a/docs/fields.md b/docs/fields.md index eed37dc..66d4dd7 100644 --- a/docs/fields.md +++ b/docs/fields.md @@ -199,7 +199,7 @@ But you can overwrite this name by providing `related_name` parameter like below Since related models are coming from Relationship Manager the reverse relation on access returns list of `wekref.proxy` to avoid circular references. !!!info - All relations are stored in lists, but when you access parent `Model` the ORM is unpacking the value for you. + All relations are stored in lists, but when you access parent `Model` the ormar is unpacking the value for you. Read more in [relations][relations]. [relations]: ./relations.md diff --git a/docs/index.md b/docs/index.md index 24756fe..cf66bba 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -# Async-ORM +# ORMar

@@ -15,42 +15,42 @@

-The `async-orm` package is an async ORM for Python, with support for Postgres, -MySQL, and SQLite. ORM is built with: +The `ormar` package is an async ORM for Python, with support for Postgres, +MySQL, and SQLite. Ormar is built with: * [`SQLAlchemy core`][sqlalchemy-core] for query building. * [`databases`][databases] for cross-database async support. * [`pydantic`][pydantic] for data validation. -Because ORM is built on SQLAlchemy core, you can use [`alembic`][alembic] to provide +Because ormar is built on SQLAlchemy core, you can use [`alembic`][alembic] to provide database migrations. -The goal was to create a simple orm that can be used directly with [`fastapi`][fastapi] that bases it's data validation on pydantic. +The goal was to create a simple ORM that can be used directly with [`fastapi`][fastapi] that bases it's data validation on pydantic. Initial work was inspired by [`encode/orm`][encode/orm]. The encode package was too simple (i.e. no ability to join two times to the same table) and used typesystem for data checks. -**async-orm is still under development:** We recommend pinning any dependencies with `aorm~=0.0.1` +**ormar is still under development:** We recommend pinning any dependencies with `ormar~=0.0.1` **Note**: Use `ipython` to try this from the console, since it supports `await`. ```python import databases -import orm +import ormar import sqlalchemy database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Note(orm.Model): +class Note(ormar.Model): __tablename__ = "notes" __database__ = database __metadata__ = metadata # primary keys of type int by dafault are set to autoincrement - id = orm.Integer(primary_key=True) - text = orm.String(length=100) - completed = orm.Boolean(default=False) + id = ormar.Integer(primary_key=True) + text = ormar.String(length=100) + completed = ormar.Boolean(default=False) # Create the database engine = sqlalchemy.create_engine(str(database.url)) @@ -84,35 +84,35 @@ note = await Note.objects.get(pk=2) note.pk # 2 ``` -ORM supports loading and filtering across foreign keys... +Ormar supports loading and filtering across foreign keys... ```python import databases -import orm +import ormar import sqlalchemy database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Album(orm.Model): +class Album(ormar.Model): __tablename__ = "album" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Track(orm.Model): +class Track(ormar.Model): __tablename__ = "track" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - album = orm.ForeignKey(Album) - title = orm.String(length=100) - position = orm.Integer() + id = ormar.Integer(primary_key=True) + album = ormar.ForeignKey(Album) + title = ormar.String(length=100) + position = ormar.Integer() # Create some records to work with. @@ -187,17 +187,17 @@ All fields are required unless one of the following is set: ### Fields Types -* `orm.String(length)` -* `orm.Text()` -* `orm.Boolean()` -* `orm.Integer()` -* `orm.Float()` -* `orm.Date()` -* `orm.Time()` -* `orm.DateTime()` -* `orm.JSON()` -* `orm.BigInteger()` -* `orm.Decimal(lenght, precision)` +* `String(length)` +* `Text()` +* `Boolean()` +* `Integer()` +* `Float()` +* `Date()` +* `Time()` +* `DateTime()` +* `JSON()` +* `BigInteger()` +* `Decimal(lenght, precision)` [sqlalchemy-core]: https://docs.sqlalchemy.org/en/latest/core/ [databases]: https://github.com/encode/databases diff --git a/docs/models.md b/docs/models.md index e4f5a13..5fd3cd6 100644 --- a/docs/models.md +++ b/docs/models.md @@ -1,17 +1,20 @@ # Models ## Defining models -By defining an orm Model you get corresponding **Pydantic model** as well as **Sqlalchemy table** for free. + +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 ORM model you simply need to inherit a `orm.Model` class. + +To build an ormar model you simply need to inherit a `ormar.Model` class. ```Python hl_lines="10" --8<-- "../docs_src/models/docs001.py" ``` ### Defining Fields + Next assign one or more of the [Fields][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. @@ -31,17 +34,18 @@ By default if you assign primary key to `Integer` field, the `autoincrement` opt You can disable by passing `autoincremant=False`. ```Python -id = orm.Integer(primary_key=True, autoincrement=False) +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 orm depends on [`databases`][databases] and [`sqlalchemy-core`][sqlalchemy-core] for database connection +Since ormar depends on [`databases`][databases] and [`sqlalchemy-core`][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][sqlalchemy connection string] format. Created instance needs to be passed to every `Model` with `__database__` parameter. @@ -55,6 +59,7 @@ Created instance needs to be passed to every `Model` with `__database__` paramet 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 `__metadata__` parameter. @@ -123,6 +128,7 @@ The fields and relations are not stored on the `Model` itself Apart from special parameters defined in the `Model` during definition (tablename, metadata etc.) the `Model` provides you with useful internals. ### Pydantic Model + To access auto created pydantic model you can use `Model.__pydantic_model__` parameter For example to list model fields you can: @@ -138,6 +144,7 @@ For example to list model fields you can: For more options visit official [pydantic][pydantic] documentation. ### Sqlalchemy Table + To access auto created sqlalchemy table you can use `Model.__table__` parameter For example to list table columns you can: @@ -153,7 +160,8 @@ For example to list table columns you can: For more options visit official [sqlalchemy-metadata][sqlalchemy-metadata] documentation. ### Fields Definition -To access orm `Fields` you can use `Model.__model_fields__` parameter + +To access ormar `Fields` you can use `Model.__model_fields__` parameter For example to list table model fields you can: diff --git a/docs/queries.md b/docs/queries.md index b931809..474a98e 100644 --- a/docs/queries.md +++ b/docs/queries.md @@ -30,7 +30,7 @@ await malibu.save() ### load() -By default when you query a table without prefetching related models, the orm will still construct +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. ```python diff --git a/docs/relations.md b/docs/relations.md index c671252..43a6e20 100644 --- a/docs/relations.md +++ b/docs/relations.md @@ -74,7 +74,7 @@ classes = await SchoolClass.objects.select_related( Since you join two times to the same table (categories) it won't work by default -> you would need to use aliases for category tables and columns. -But don't worry - orm can handle situations like this, as it uses the Relationship Manager which has it's aliases defined for all relationships. +But don't worry - ormar can handle situations like this, as it uses the Relationship Manager which has it's aliases defined for all relationships. Each class is registered with the same instance of the RelationshipManager that you can access like this: @@ -110,7 +110,7 @@ print(Teacher._orm_relationship_manager.resolve_relation_join( ### Query automatic construction -Orm is using those aliases during queries to both construct a meaningful and valid sql, +Ormar is using those aliases during queries to both construct a meaningful and valid sql, as well as later use it to extract proper columns for proper nested models. Running a previously mentioned query to select school classes and related teachers and students: diff --git a/docs_src/fields/docs001.py b/docs_src/fields/docs001.py index f28b9d0..047690d 100644 --- a/docs_src/fields/docs001.py +++ b/docs_src/fields/docs001.py @@ -1,28 +1,28 @@ import databases import sqlalchemy -import orm +import ormar database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Department(orm.Model): +class Department(ormar.Model): __database__ = database __metadata__ = metadata - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Course(orm.Model): +class Course(ormar.Model): __database__ = database __metadata__ = metadata - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - completed = orm.Boolean(default=False) - department = orm.ForeignKey(Department) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + completed = ormar.Boolean(default=False) + department = ormar.ForeignKey(Department) department = Department(name='Science') diff --git a/docs_src/fields/docs002.py b/docs_src/fields/docs002.py index 5c9f4a9..7fa6ccd 100644 --- a/docs_src/fields/docs002.py +++ b/docs_src/fields/docs002.py @@ -1,28 +1,28 @@ import databases import sqlalchemy -import orm +import ormar database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Department(orm.Model): +class Department(ormar.Model): __database__ = database __metadata__ = metadata - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Course(orm.Model): +class Course(ormar.Model): __database__ = database __metadata__ = metadata - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - completed = orm.Boolean(default=False) - department = orm.ForeignKey(Department, related_name="my_courses") + id = ormar.Integer(primary_key=True) + name = ormar.String(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) diff --git a/docs_src/fields/docs003.py b/docs_src/fields/docs003.py index c3df501..32ff68c 100644 --- a/docs_src/fields/docs003.py +++ b/docs_src/fields/docs003.py @@ -1,4 +1,4 @@ -import orm +import ormar import databases import sqlalchemy @@ -6,24 +6,24 @@ database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Album(orm.Model): +class Album(ormar.Model): __tablename__ = "album" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Track(orm.Model): +class Track(ormar.Model): __tablename__ = "track" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - album = orm.ForeignKey(Album, nullable=False) - title = orm.String(length=100) - position = orm.Integer() + id = ormar.Integer(primary_key=True) + album = ormar.ForeignKey(Album, nullable=False) + title = ormar.String(length=100) + position = ormar.Integer() album = await Album.objects.create(name="Brooklyn") diff --git a/docs_src/models/docs001.py b/docs_src/models/docs001.py index 6aba0ed..9c8f8f1 100644 --- a/docs_src/models/docs001.py +++ b/docs_src/models/docs001.py @@ -1,16 +1,16 @@ import databases import sqlalchemy -import orm +import ormar database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Course(orm.Model): +class Course(ormar.Model): __database__ = database __metadata__ = metadata - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - completed = orm.Boolean(default=False) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + completed = ormar.Boolean(default=False) diff --git a/docs_src/models/docs002.py b/docs_src/models/docs002.py index 0886dcc..1d63371 100644 --- a/docs_src/models/docs002.py +++ b/docs_src/models/docs002.py @@ -1,19 +1,19 @@ import databases import sqlalchemy -import orm +import ormar database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Course(orm.Model): +class Course(ormar.Model): # 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 = orm.Integer(primary_key=True) - name = orm.String(length=100) - completed = orm.Boolean(default=False) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + completed = ormar.Boolean(default=False) diff --git a/docs_src/models/docs003.py b/docs_src/models/docs003.py index bd108d4..754f6d4 100644 --- a/docs_src/models/docs003.py +++ b/docs_src/models/docs003.py @@ -1,19 +1,19 @@ import databases import sqlalchemy -import orm +import ormar database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Course(orm.Model): +class Course(ormar.Model): __database__ = database __metadata__ = metadata - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - completed = orm.Boolean(default=False) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + completed = ormar.Boolean(default=False) print(Course.__pydantic_model__.__fields__) """ diff --git a/docs_src/models/docs004.py b/docs_src/models/docs004.py index f2f06ba..36e5da0 100644 --- a/docs_src/models/docs004.py +++ b/docs_src/models/docs004.py @@ -1,19 +1,19 @@ import databases import sqlalchemy -import orm +import ormar database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Course(orm.Model): +class Course(ormar.Model): __database__ = database __metadata__ = metadata - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - completed = orm.Boolean(default=False) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + completed = ormar.Boolean(default=False) print(Course.__table__.columns) """ diff --git a/docs_src/models/docs005.py b/docs_src/models/docs005.py index cf33c9d..e1a85e8 100644 --- a/docs_src/models/docs005.py +++ b/docs_src/models/docs005.py @@ -1,19 +1,19 @@ import databases import sqlalchemy -import orm +import ormar database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Course(orm.Model): +class Course(ormar.Model): __database__ = database __metadata__ = metadata - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - completed = orm.Boolean(default=False) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + completed = ormar.Boolean(default=False) print(Course.__model_fields__) """ diff --git a/docs_src/models/docs006.py b/docs_src/models/docs006.py index fc0fbef..b232979 100644 --- a/docs_src/models/docs006.py +++ b/docs_src/models/docs006.py @@ -1,28 +1,28 @@ import databases import sqlalchemy -import orm +import ormar database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Department(orm.Model): +class Department(ormar.Model): __database__ = database __metadata__ = metadata - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Course(orm.Model): +class Course(ormar.Model): __database__ = database __metadata__ = metadata - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - completed = orm.Boolean(default=False) - department = orm.ForeignKey(Department) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + completed = ormar.Boolean(default=False) + department = ormar.ForeignKey(Department) department = Department(name="Science") diff --git a/docs_src/models/docs007.py b/docs_src/models/docs007.py index 2bd7af1..f98e62a 100644 --- a/docs_src/models/docs007.py +++ b/docs_src/models/docs007.py @@ -1,19 +1,19 @@ import databases import sqlalchemy -import orm +import ormar database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Course(orm.Model): +class Course(ormar.Model): __database__ = database __metadata__ = metadata - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - completed = orm.Boolean(default=False) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + completed = ormar.Boolean(default=False) course = Course(name="Painting for dummies", completed=False) diff --git a/docs_src/relations/docs001.py b/docs_src/relations/docs001.py index 4a028c3..53e2f5c 100644 --- a/docs_src/relations/docs001.py +++ b/docs_src/relations/docs001.py @@ -1,4 +1,4 @@ -import orm +import ormar import databases import sqlalchemy @@ -6,21 +6,21 @@ database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Album(orm.Model): +class Album(ormar.Model): __tablename__ = "album" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Track(orm.Model): +class Track(ormar.Model): __tablename__ = "track" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - album = orm.ForeignKey(Album) - title = orm.String(length=100) - position = orm.Integer() \ No newline at end of file + id = ormar.Integer(primary_key=True) + album = ormar.ForeignKey(Album) + title = ormar.String(length=100) + position = ormar.Integer() \ No newline at end of file diff --git a/docs_src/relations/docs002.py b/docs_src/relations/docs002.py index 9e3dfda..ef67093 100644 --- a/docs_src/relations/docs002.py +++ b/docs_src/relations/docs002.py @@ -1,4 +1,4 @@ -import orm +import ormar import databases import sqlalchemy @@ -6,24 +6,24 @@ database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class Album(orm.Model): +class Album(ormar.Model): __tablename__ = "album" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Track(orm.Model): +class Track(ormar.Model): __tablename__ = "track" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - album = orm.ForeignKey(Album) - title = orm.String(length=100) - position = orm.Integer() + id = ormar.Integer(primary_key=True) + album = ormar.ForeignKey(Album) + title = ormar.String(length=100) + position = ormar.Integer() print(Track.__table__.columns['album'].__repr__()) diff --git a/docs_src/relations/docs003.py b/docs_src/relations/docs003.py index aa54c29..e319e42 100644 --- a/docs_src/relations/docs003.py +++ b/docs_src/relations/docs003.py @@ -1,44 +1,44 @@ import databases import sqlalchemy -import orm +import ormar database = databases.Database("sqlite:///db.sqlite") metadata = sqlalchemy.MetaData() -class SchoolClass(orm.Model): +class SchoolClass(ormar.Model): __tablename__ = "schoolclasses" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Category(orm.Model): +class Category(ormar.Model): __tablename__ = "categories" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Student(orm.Model): +class Student(ormar.Model): __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - schoolclass = orm.ForeignKey(SchoolClass) - category = orm.ForeignKey(Category) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + schoolclass = ormar.ForeignKey(SchoolClass) + category = ormar.ForeignKey(Category) -class Teacher(orm.Model): +class Teacher(ormar.Model): __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - schoolclass = orm.ForeignKey(SchoolClass) - category = orm.ForeignKey(Category) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + schoolclass = ormar.ForeignKey(SchoolClass) + category = ormar.ForeignKey(Category) diff --git a/orm/models/__init__.py b/orm/models/__init__.py deleted file mode 100644 index b948f31..0000000 --- a/orm/models/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from orm.models.fakepydantic import FakePydantic -from orm.models.model import Model - -__all__ = ["FakePydantic", "Model"] diff --git a/orm/queryset/__init__.py b/orm/queryset/__init__.py deleted file mode 100644 index 30e112a..0000000 --- a/orm/queryset/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from orm.queryset.queryset import QuerySet - -__all__ = ["QuerySet"] diff --git a/orm/__init__.py b/ormar/__init__.py similarity index 72% rename from orm/__init__.py rename to ormar/__init__.py index 2cf9401..1d9f65c 100644 --- a/orm/__init__.py +++ b/ormar/__init__.py @@ -1,5 +1,5 @@ -from orm.exceptions import ModelDefinitionError, ModelNotSet, MultipleMatches, NoMatch -from orm.fields import ( +from ormar.exceptions import ModelDefinitionError, ModelNotSet, MultipleMatches, NoMatch +from ormar.fields import ( BigInteger, Boolean, Date, @@ -13,9 +13,9 @@ from orm.fields import ( Text, Time, ) -from orm.models import Model +from ormar.models import Model -__version__ = "0.0.1" +__version__ = "0.1.0" __all__ = [ "Integer", "BigInteger", diff --git a/orm/exceptions.py b/ormar/exceptions.py similarity index 100% rename from orm/exceptions.py rename to ormar/exceptions.py diff --git a/orm/fields/__init__.py b/ormar/fields/__init__.py similarity index 72% rename from orm/fields/__init__.py rename to ormar/fields/__init__.py index 6355c38..f6c4dc9 100644 --- a/orm/fields/__init__.py +++ b/ormar/fields/__init__.py @@ -1,6 +1,6 @@ -from orm.fields.base import BaseField -from orm.fields.foreign_key import ForeignKey -from orm.fields.model_fields import ( +from ormar.fields.base import BaseField +from ormar.fields.foreign_key import ForeignKey +from ormar.fields.model_fields import ( BigInteger, Boolean, Date, diff --git a/orm/fields/base.py b/ormar/fields/base.py similarity index 96% rename from orm/fields/base.py rename to ormar/fields/base.py index 003d14e..cef323f 100644 --- a/orm/fields/base.py +++ b/ormar/fields/base.py @@ -2,10 +2,10 @@ from typing import Any, Dict, List, Optional, TYPE_CHECKING import sqlalchemy -from orm import ModelDefinitionError # noqa I101 +from ormar import ModelDefinitionError # noqa I101 if TYPE_CHECKING: # pragma no cover - from orm.models import Model + from ormar.models import Model class BaseField: diff --git a/orm/fields/decorators.py b/ormar/fields/decorators.py similarity index 91% rename from orm/fields/decorators.py rename to ormar/fields/decorators.py index ae4e498..842e864 100644 --- a/orm/fields/decorators.py +++ b/ormar/fields/decorators.py @@ -1,9 +1,9 @@ from typing import Any, TYPE_CHECKING, Type -from orm import ModelDefinitionError +from ormar import ModelDefinitionError if TYPE_CHECKING: # pragma no cover - from orm.fields import BaseField + from ormar.fields import BaseField class RequiredParams: diff --git a/orm/fields/foreign_key.py b/ormar/fields/foreign_key.py similarity index 95% rename from orm/fields/foreign_key.py rename to ormar/fields/foreign_key.py index 839ca95..77c2da7 100644 --- a/orm/fields/foreign_key.py +++ b/ormar/fields/foreign_key.py @@ -3,12 +3,12 @@ from typing import Any, List, Optional, TYPE_CHECKING, Type, Union import sqlalchemy from pydantic import BaseModel -import orm # noqa I101 -from orm.exceptions import RelationshipInstanceError -from orm.fields.base import BaseField +import ormar # noqa I101 +from ormar.exceptions import RelationshipInstanceError +from ormar.fields.base import BaseField if TYPE_CHECKING: # pragma no cover - from orm.models import Model + from ormar.models import Model def create_dummy_instance(fk: Type["Model"], pk: Any = None) -> "Model": diff --git a/orm/fields/model_fields.py b/ormar/fields/model_fields.py similarity index 94% rename from orm/fields/model_fields.py rename to ormar/fields/model_fields.py index f14391e..4f9be11 100644 --- a/orm/fields/model_fields.py +++ b/ormar/fields/model_fields.py @@ -4,8 +4,8 @@ import decimal import sqlalchemy from pydantic import Json -from orm.fields.base import BaseField # noqa I101 -from orm.fields.decorators import RequiredParams +from ormar.fields.base import BaseField # noqa I101 +from ormar.fields.decorators import RequiredParams @RequiredParams("length") diff --git a/ormar/models/__init__.py b/ormar/models/__init__.py new file mode 100644 index 0000000..b70c515 --- /dev/null +++ b/ormar/models/__init__.py @@ -0,0 +1,4 @@ +from ormar.models.fakepydantic import FakePydantic +from ormar.models.model import Model + +__all__ = ["FakePydantic", "Model"] diff --git a/orm/models/fakepydantic.py b/ormar/models/fakepydantic.py similarity index 95% rename from orm/models/fakepydantic.py rename to ormar/models/fakepydantic.py index 5e1d6b4..c7a1bc8 100644 --- a/orm/models/fakepydantic.py +++ b/ormar/models/fakepydantic.py @@ -19,13 +19,13 @@ import pydantic import sqlalchemy from pydantic import BaseModel -import orm # noqa I100 -from orm.fields import BaseField -from orm.models.metaclass import ModelMetaclass -from orm.relations import RelationshipManager +import ormar # noqa I100 +from ormar.fields import BaseField +from ormar.models.metaclass import ModelMetaclass +from ormar.relations import RelationshipManager if TYPE_CHECKING: # pragma no cover - from orm.models.model import Model + from ormar.models.model import Model class FakePydantic(list, metaclass=ModelMetaclass): @@ -194,10 +194,10 @@ class FakePydantic(list, metaclass=ModelMetaclass): def merge_two_instances(cls, one: "Model", other: "Model") -> "Model": for field in one.__model_fields__.keys(): if isinstance(getattr(one, field), list) and not isinstance( - getattr(one, field), orm.Model + getattr(one, field), ormar.Model ): setattr(other, field, getattr(one, field) + getattr(other, field)) - elif isinstance(getattr(one, field), orm.Model): + elif isinstance(getattr(one, field), ormar.Model): if getattr(one, field).pk == getattr(other, field).pk: setattr( other, diff --git a/orm/models/metaclass.py b/ormar/models/metaclass.py similarity index 96% rename from orm/models/metaclass.py rename to ormar/models/metaclass.py index f519791..7ea2fe7 100644 --- a/orm/models/metaclass.py +++ b/ormar/models/metaclass.py @@ -5,12 +5,12 @@ import sqlalchemy from pydantic import BaseConfig, create_model from pydantic.fields import ModelField -from orm import ForeignKey, ModelDefinitionError # noqa I100 -from orm.fields import BaseField -from orm.relations import RelationshipManager +from ormar import ForeignKey, ModelDefinitionError # noqa I100 +from ormar.fields import BaseField +from ormar.relations import RelationshipManager if TYPE_CHECKING: # pragma no cover - from orm import Model + from ormar import Model relationship_manager = RelationshipManager() diff --git a/orm/models/model.py b/ormar/models/model.py similarity index 95% rename from orm/models/model.py rename to ormar/models/model.py index ab21bfc..fed4224 100644 --- a/orm/models/model.py +++ b/ormar/models/model.py @@ -2,14 +2,14 @@ from typing import Any, List import sqlalchemy -import orm.queryset # noqa I100 -from orm.models import FakePydantic # noqa I100 +import ormar.queryset # noqa I100 +from ormar.models import FakePydantic # noqa I100 class Model(FakePydantic): __abstract__ = True - objects = orm.queryset.QuerySet() + objects = ormar.queryset.QuerySet() @classmethod def from_row( diff --git a/ormar/queryset/__init__.py b/ormar/queryset/__init__.py new file mode 100644 index 0000000..7bf6fc6 --- /dev/null +++ b/ormar/queryset/__init__.py @@ -0,0 +1,3 @@ +from ormar.queryset.queryset import QuerySet + +__all__ = ["QuerySet"] diff --git a/orm/queryset/clause.py b/ormar/queryset/clause.py similarity index 96% rename from orm/queryset/clause.py rename to ormar/queryset/clause.py index e70aaa1..3d5d14b 100644 --- a/orm/queryset/clause.py +++ b/ormar/queryset/clause.py @@ -3,11 +3,11 @@ from typing import Any, Dict, List, Optional, TYPE_CHECKING, Tuple, Type, Union import sqlalchemy from sqlalchemy import text -import orm # noqa I100 -from orm.exceptions import QueryDefinitionError +import ormar # noqa I100 +from ormar.exceptions import QueryDefinitionError if TYPE_CHECKING: # pragma no cover - from orm import Model + from ormar import Model FILTER_OPERATORS = { "exact": "__eq__", @@ -75,7 +75,7 @@ class QueryClause: value, has_escaped_character = self._escape_characters_in_clause(op, value) - if isinstance(value, orm.Model): + if isinstance(value, ormar.Model): value = value.pk op_attr = FILTER_OPERATORS[op] @@ -147,7 +147,7 @@ class QueryClause: if op not in ["contains", "icontains"]: return value, has_escaped_character - if isinstance(value, orm.Model): + if isinstance(value, ormar.Model): raise QueryDefinitionError( "You cannot use contains and icontains with instance of the Model" ) diff --git a/orm/queryset/query.py b/ormar/queryset/query.py similarity index 97% rename from orm/queryset/query.py rename to ormar/queryset/query.py index bf6234f..202b249 100644 --- a/orm/queryset/query.py +++ b/ormar/queryset/query.py @@ -3,12 +3,12 @@ from typing import List, NamedTuple, TYPE_CHECKING, Tuple, Type import sqlalchemy from sqlalchemy import text -import orm # noqa I100 -from orm import ForeignKey -from orm.fields import BaseField +import ormar # noqa I100 +from ormar import ForeignKey +from ormar.fields import BaseField if TYPE_CHECKING: # pragma no cover - from orm import Model + from ormar import Model class JoinParameters(NamedTuple): @@ -53,7 +53,7 @@ class Query: if ( not self.model_cls.__model_fields__[key].nullable and isinstance( - self.model_cls.__model_fields__[key], orm.fields.ForeignKey, + self.model_cls.__model_fields__[key], ormar.fields.ForeignKey, ) and key not in self._select_related ): diff --git a/orm/queryset/queryset.py b/ormar/queryset/queryset.py similarity index 96% rename from orm/queryset/queryset.py rename to ormar/queryset/queryset.py index 5cbc3cd..3190036 100644 --- a/orm/queryset/queryset.py +++ b/ormar/queryset/queryset.py @@ -3,13 +3,13 @@ from typing import Any, List, TYPE_CHECKING, Tuple, Type, Union import databases import sqlalchemy -import orm # noqa I100 -from orm import MultipleMatches, NoMatch -from orm.queryset.clause import QueryClause -from orm.queryset.query import Query +import ormar # noqa I100 +from ormar import MultipleMatches, NoMatch +from ormar.queryset.clause import QueryClause +from ormar.queryset.query import Query if TYPE_CHECKING: # pragma no cover - from orm import Model + from ormar import Model class QuerySet: diff --git a/orm/relations.py b/ormar/relations.py similarity index 97% rename from orm/relations.py rename to ormar/relations.py index 9df7ee7..45c3ddd 100644 --- a/orm/relations.py +++ b/ormar/relations.py @@ -5,10 +5,10 @@ from random import choices from typing import List, TYPE_CHECKING, Union from weakref import proxy -from orm import ForeignKey +from ormar import ForeignKey if TYPE_CHECKING: # pragma no cover - from orm.models import FakePydantic, Model + from ormar.models import FakePydantic, Model def get_table_alias() -> str: diff --git a/scripts/clean.sh b/scripts/clean.sh old mode 100644 new mode 100755 index 38b8eb7..9b30e14 --- a/scripts/clean.sh +++ b/scripts/clean.sh @@ -1,5 +1,5 @@ #!/bin/sh -e -PACKAGE="orm" +PACKAGE="ormar" if [ -d 'dist' ] ; then rm -r dist fi diff --git a/scripts/publish.sh b/scripts/publish.sh new file mode 100644 index 0000000..419fa30 --- /dev/null +++ b/scripts/publish.sh @@ -0,0 +1,23 @@ +#!/bin/sh -e + +PACKAGE="ormar" + +PREFIX="" +if [ -d 'venv' ] ; then + PREFIX="venv/bin/" +fi + +VERSION=`cat ${PACKAGE}/__init__.py | grep __version__ | sed "s/__version__ = //" | sed "s/'//g"` + +set -x + +scripts/clean.sh + +${PREFIX}python setup.py sdist +${PREFIX}twine upload dist/* + +echo "You probably want to also tag the version now:" +echo "git tag -a ${VERSION} -m 'version ${VERSION}'" +echo "git push --tags" + +scripts/clean.sh \ No newline at end of file diff --git a/scripts/test.sh b/scripts/test.sh index 11c09f6..c911ffb 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -PACKAGE="orm" +PACKAGE="ormar" PREFIX="" if [ -d 'venv' ] ; then diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..224a779 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[metadata] +description-file = README.md \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..4b88c2d --- /dev/null +++ b/setup.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os +import re + +from setuptools import setup + +PACKAGE = "ormar" +URL = "https://github.com/collerek/ormar" + + +def get_version(package): + """ + Return package version as listed in `__version__` in `init.py`. + """ + with open(os.path.join(package, "__init__.py")) as f: + return re.search("__version__ = ['\"]([^'\"]+)['\"]", f.read()).group(1) + + +def get_long_description(): + """ + Return the README. + """ + with open("README.md", encoding="utf8") as f: + return f.read() + + +def get_packages(package): + """ + Return root package and all sub-packages. + """ + return [ + dirpath + for dirpath, dirnames, filenames in os.walk(package) + if os.path.exists(os.path.join(dirpath, "__init__.py")) + ] + + +setup( + name=PACKAGE, + version=get_version(PACKAGE), + url=URL, + license="MIT", + description="An simple async ORM with Fastapi in mind.", + long_description=get_long_description(), + long_description_content_type="text/markdown", + keywords=['ORM', 'sqlalchemy', 'fastapi', 'pydantic', 'databases'], + author="Radosław Drążkiewicz", + author_email="collerek@gmail.com", + packages=get_packages(PACKAGE), + package_data={PACKAGE: ["py.typed"]}, + data_files=[("", ["LICENSE.md"])], + install_requires=["databases", "pydantic", "sqlalchemy"], + classifiers=[ + "Development Status :: 3 - Alpha", + "Environment :: Web Environment", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Topic :: Internet :: WWW/HTTP", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + ], +) diff --git a/tests/test_columns.py b/tests/test_columns.py index edee116..e75cb0a 100644 --- a/tests/test_columns.py +++ b/tests/test_columns.py @@ -4,7 +4,7 @@ import databases import pytest import sqlalchemy -import orm +import ormar from tests.settings import DATABASE_URL database = databases.Database(DATABASE_URL, force_rollback=True) @@ -15,18 +15,18 @@ def time(): return datetime.datetime.now().time() -class Example(orm.Model): +class Example(ormar.Model): __tablename__ = "example" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - created = orm.DateTime(default=datetime.datetime.now) - created_day = orm.Date(default=datetime.date.today) - created_time = orm.Time(default=time) - description = orm.Text(nullable=True) - value = orm.Float(nullable=True) - data = orm.JSON(default={}) + id = ormar.Integer(primary_key=True) + created = ormar.DateTime(default=datetime.datetime.now) + created_day = ormar.Date(default=datetime.date.today) + created_time = ormar.Time(default=time) + description = ormar.Text(nullable=True) + value = ormar.Float(nullable=True) + data = ormar.JSON(default={}) @pytest.fixture(autouse=True, scope="module") diff --git a/tests/test_fastapi_usage.py b/tests/test_fastapi_usage.py index bef1607..25b1310 100644 --- a/tests/test_fastapi_usage.py +++ b/tests/test_fastapi_usage.py @@ -3,8 +3,7 @@ import sqlalchemy from fastapi import FastAPI from fastapi.testclient import TestClient -import orm -import orm.fields.foreign_key +import ormar from tests.settings import DATABASE_URL app = FastAPI() @@ -13,23 +12,23 @@ database = databases.Database(DATABASE_URL, force_rollback=True) metadata = sqlalchemy.MetaData() -class Category(orm.Model): +class Category(ormar.Model): __tablename__ = "categories" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Item(orm.Model): +class Item(ormar.Model): __tablename__ = "items" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - category = orm.fields.foreign_key.ForeignKey(Category, nullable=True) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + category = ormar.ForeignKey(Category, nullable=True) @app.post("/items/", response_model=Item) diff --git a/tests/test_foreign_keys.py b/tests/test_foreign_keys.py index aaea6ff..45f4359 100644 --- a/tests/test_foreign_keys.py +++ b/tests/test_foreign_keys.py @@ -2,71 +2,71 @@ import databases import pytest import sqlalchemy -import orm -from orm.exceptions import NoMatch, MultipleMatches, RelationshipInstanceError +import ormar +from ormar.exceptions import NoMatch, MultipleMatches, RelationshipInstanceError from tests.settings import DATABASE_URL database = databases.Database(DATABASE_URL, force_rollback=True) metadata = sqlalchemy.MetaData() -class Album(orm.Model): +class Album(ormar.Model): __tablename__ = "album" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Track(orm.Model): +class Track(ormar.Model): __tablename__ = "track" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - album = orm.ForeignKey(Album) - title = orm.String(length=100) - position = orm.Integer() + id = ormar.Integer(primary_key=True) + album = ormar.ForeignKey(Album) + title = ormar.String(length=100) + position = ormar.Integer() -class Cover(orm.Model): +class Cover(ormar.Model): __tablename__ = "covers" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - album = orm.ForeignKey(Album, related_name='cover_pictures') - title = orm.String(length=100) + id = ormar.Integer(primary_key=True) + album = ormar.ForeignKey(Album, related_name='cover_pictures') + title = ormar.String(length=100) -class Organisation(orm.Model): +class Organisation(ormar.Model): __tablename__ = "org" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - ident = orm.String(length=100) + id = ormar.Integer(primary_key=True) + ident = ormar.String(length=100) -class Team(orm.Model): +class Team(ormar.Model): __tablename__ = "team" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - org = orm.ForeignKey(Organisation) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + org = ormar.ForeignKey(Organisation) + name = ormar.String(length=100) -class Member(orm.Model): +class Member(ormar.Model): __tablename__ = "member" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - team = orm.ForeignKey(Team) - email = orm.String(length=100) + id = ormar.Integer(primary_key=True) + team = ormar.ForeignKey(Team) + email = ormar.String(length=100) @pytest.fixture(autouse=True, scope="module") diff --git a/tests/test_model_definition.py b/tests/test_model_definition.py index 8ea9289..253ae4f 100644 --- a/tests/test_model_definition.py +++ b/tests/test_model_definition.py @@ -4,9 +4,9 @@ import pydantic import pytest import sqlalchemy -import orm.fields as fields -from orm.exceptions import ModelDefinitionError -from orm.models import Model +import ormar.fields as fields +from ormar.exceptions import ModelDefinitionError +from ormar.models import Model metadata = sqlalchemy.MetaData() diff --git a/tests/test_models.py b/tests/test_models.py index 8b0bf37..69d421c 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -2,32 +2,32 @@ import databases import pytest import sqlalchemy -import orm -from orm.exceptions import QueryDefinitionError +import ormar +from ormar.exceptions import QueryDefinitionError from tests.settings import DATABASE_URL database = databases.Database(DATABASE_URL, force_rollback=True) metadata = sqlalchemy.MetaData() -class User(orm.Model): +class User(ormar.Model): __tablename__ = "users" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Product(orm.Model): +class Product(ormar.Model): __tablename__ = "product" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - rating = orm.Integer(minimum=1, maximum=5) - in_stock = orm.Boolean(default=False) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + rating = ormar.Integer(minimum=1, maximum=5) + in_stock = ormar.Boolean(default=False) @pytest.fixture(autouse=True, scope="module") @@ -40,9 +40,9 @@ def create_test_database(): def test_model_class(): assert list(User.__model_fields__.keys()) == ["id", "name"] - assert isinstance(User.__model_fields__["id"], orm.Integer) + assert isinstance(User.__model_fields__["id"], ormar.Integer) assert User.__model_fields__["id"].primary_key is True - assert isinstance(User.__model_fields__["name"], orm.String) + assert isinstance(User.__model_fields__["name"], ormar.String) assert User.__model_fields__["name"].length == 100 assert isinstance(User.__table__, sqlalchemy.Table) @@ -82,7 +82,7 @@ async def test_model_crud(): @pytest.mark.asyncio async def test_model_get(): async with database: - with pytest.raises(orm.NoMatch): + with pytest.raises(ormar.NoMatch): await User.objects.get() user = await User.objects.create(name="Tom") @@ -90,7 +90,7 @@ async def test_model_get(): assert lookup == user user = await User.objects.create(name="Jane") - with pytest.raises(orm.MultipleMatches): + with pytest.raises(ormar.MultipleMatches): await User.objects.get() same_user = await User.objects.get(pk=user.id) @@ -108,7 +108,7 @@ async def test_model_filter(): user = await User.objects.get(name="Lucy") assert user.name == "Lucy" - with pytest.raises(orm.NoMatch): + with pytest.raises(ormar.NoMatch): await User.objects.get(name="Jim") await Product.objects.create(name="T-Shirt", rating=5, in_stock=True) diff --git a/tests/test_same_table_joins.py b/tests/test_same_table_joins.py index b1dd02a..69f5dd2 100644 --- a/tests/test_same_table_joins.py +++ b/tests/test_same_table_joins.py @@ -4,62 +4,61 @@ import databases import pytest import sqlalchemy -import orm -import orm.fields.foreign_key +import ormar from tests.settings import DATABASE_URL database = databases.Database(DATABASE_URL, force_rollback=True) metadata = sqlalchemy.MetaData() -class Department(orm.Model): +class Department(ormar.Model): __tablename__ = "departments" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True, autoincrement=False) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True, autoincrement=False) + name = ormar.String(length=100) -class SchoolClass(orm.Model): +class SchoolClass(ormar.Model): __tablename__ = "schoolclasses" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - department = orm.fields.foreign_key.ForeignKey(Department, nullable=False) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + department = ormar.ForeignKey(Department, nullable=False) -class Category(orm.Model): +class Category(ormar.Model): __tablename__ = "categories" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) -class Student(orm.Model): +class Student(ormar.Model): __tablename__ = "students" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - schoolclass = orm.fields.foreign_key.ForeignKey(SchoolClass) - category = orm.fields.foreign_key.ForeignKey(Category, nullable=True) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + schoolclass = ormar.ForeignKey(SchoolClass) + category = ormar.ForeignKey(Category, nullable=True) -class Teacher(orm.Model): +class Teacher(ormar.Model): __tablename__ = "teachers" __metadata__ = metadata __database__ = database - id = orm.Integer(primary_key=True) - name = orm.String(length=100) - schoolclass = orm.fields.foreign_key.ForeignKey(SchoolClass) - category = orm.fields.foreign_key.ForeignKey(Category, nullable=True) + id = ormar.Integer(primary_key=True) + name = ormar.String(length=100) + schoolclass = ormar.ForeignKey(SchoolClass) + category = ormar.ForeignKey(Category, nullable=True) @pytest.fixture(scope='module')