split tests into packages
This commit is contained in:
0
tests/test_deferred/__init__.py
Normal file
0
tests/test_deferred/__init__.py
Normal file
116
tests/test_deferred/test_forward_cross_refs.py
Normal file
116
tests/test_deferred/test_forward_cross_refs.py
Normal file
@ -0,0 +1,116 @@
|
||||
# type: ignore
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy as sa
|
||||
from pydantic.typing import ForwardRef
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
import ormar
|
||||
from ormar import ModelMeta
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
metadata = sa.MetaData()
|
||||
db = databases.Database(DATABASE_URL)
|
||||
engine = create_engine(DATABASE_URL)
|
||||
|
||||
TeacherRef = ForwardRef("Teacher")
|
||||
|
||||
|
||||
class Student(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
primary_teacher: TeacherRef = ormar.ForeignKey(
|
||||
TeacherRef, related_name="own_students"
|
||||
)
|
||||
|
||||
|
||||
class StudentTeacher(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
tablename = "students_x_teachers"
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
|
||||
class Teacher(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
students = ormar.ManyToMany(
|
||||
Student, through=StudentTeacher, related_name="teachers"
|
||||
)
|
||||
|
||||
|
||||
Student.update_forward_refs()
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_double_relations():
|
||||
async with db:
|
||||
async with db.transaction(force_rollback=True):
|
||||
t1 = await Teacher.objects.create(name="Mr. Jones")
|
||||
t2 = await Teacher.objects.create(name="Ms. Smith")
|
||||
t3 = await Teacher.objects.create(name="Mr. Quibble")
|
||||
|
||||
s1 = await Student.objects.create(name="Joe", primary_teacher=t1)
|
||||
s2 = await Student.objects.create(name="Sam", primary_teacher=t1)
|
||||
s3 = await Student.objects.create(name="Kate", primary_teacher=t2)
|
||||
s4 = await Student.objects.create(name="Zoe", primary_teacher=t2)
|
||||
s5 = await Student.objects.create(name="John", primary_teacher=t3)
|
||||
s6 = await Student.objects.create(name="Anna", primary_teacher=t3)
|
||||
|
||||
for t in [t1, t2, t3]:
|
||||
for s in [s1, s2, s3, s4, s5, s6]:
|
||||
await t.students.add(s)
|
||||
|
||||
jones = (
|
||||
await Teacher.objects.select_related(["students", "own_students"])
|
||||
.order_by(["students__name", "own_students__name"])
|
||||
.get(name="Mr. Jones")
|
||||
)
|
||||
assert len(jones.students) == 6
|
||||
assert jones.students[0].name == "Anna"
|
||||
assert jones.students[5].name == "Zoe"
|
||||
assert len(jones.own_students) == 2
|
||||
assert jones.own_students[0].name == "Joe"
|
||||
assert jones.own_students[1].name == "Sam"
|
||||
|
||||
smith = (
|
||||
await Teacher.objects.select_related(["students", "own_students"])
|
||||
.filter(students__name__contains="a")
|
||||
.order_by(["students__name", "own_students__name"])
|
||||
.get(name="Ms. Smith")
|
||||
)
|
||||
assert len(smith.students) == 3
|
||||
assert smith.students[0].name == "Anna"
|
||||
assert smith.students[2].name == "Sam"
|
||||
assert len(smith.own_students) == 2
|
||||
assert smith.own_students[0].name == "Kate"
|
||||
assert smith.own_students[1].name == "Zoe"
|
||||
|
||||
quibble = (
|
||||
await Teacher.objects.select_related(["students", "own_students"])
|
||||
.filter(students__name__startswith="J")
|
||||
.order_by(["-students__name", "own_students__name"])
|
||||
.get(name="Mr. Quibble")
|
||||
)
|
||||
assert len(quibble.students) == 2
|
||||
assert quibble.students[1].name == "Joe"
|
||||
assert quibble.students[0].name == "John"
|
||||
assert len(quibble.own_students) == 2
|
||||
assert quibble.own_students[1].name == "John"
|
||||
assert quibble.own_students[0].name == "Anna"
|
||||
304
tests/test_deferred/test_forward_refs.py
Normal file
304
tests/test_deferred/test_forward_refs.py
Normal file
@ -0,0 +1,304 @@
|
||||
# type: ignore
|
||||
from typing import List
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy as sa
|
||||
from pydantic.typing import ForwardRef
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
import ormar
|
||||
from ormar import ModelMeta
|
||||
from ormar.exceptions import ModelError
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
metadata = sa.MetaData()
|
||||
db = databases.Database(DATABASE_URL)
|
||||
engine = create_engine(DATABASE_URL)
|
||||
|
||||
PersonRef = ForwardRef("Person")
|
||||
|
||||
|
||||
class Person(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
supervisor: PersonRef = ormar.ForeignKey(PersonRef, related_name="employees")
|
||||
|
||||
|
||||
Person.update_forward_refs()
|
||||
|
||||
GameRef = ForwardRef("Game")
|
||||
ChildRef = ForwardRef("Child")
|
||||
ChildFriendRef = ForwardRef("ChildFriend")
|
||||
|
||||
|
||||
class Child(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
favourite_game: GameRef = ormar.ForeignKey(GameRef, related_name="liked_by")
|
||||
least_favourite_game: GameRef = ormar.ForeignKey(
|
||||
GameRef, related_name="not_liked_by"
|
||||
)
|
||||
friends = ormar.ManyToMany(
|
||||
ChildRef, through=ChildFriendRef, related_name="also_friends"
|
||||
)
|
||||
|
||||
|
||||
class ChildFriend(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
|
||||
class Game(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
Child.update_forward_refs()
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
async def cleanup():
|
||||
yield
|
||||
async with db:
|
||||
await ChildFriend.objects.delete(each=True)
|
||||
await Child.objects.delete(each=True)
|
||||
await Game.objects.delete(each=True)
|
||||
await Person.objects.delete(each=True)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_not_updated_model_raises_errors():
|
||||
Person2Ref = ForwardRef("Person2")
|
||||
|
||||
class Person2(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
supervisor: Person2Ref = ormar.ForeignKey(Person2Ref, related_name="employees")
|
||||
|
||||
with pytest.raises(ModelError):
|
||||
await Person2.objects.create(name="Test")
|
||||
|
||||
with pytest.raises(ModelError):
|
||||
Person2(name="Test")
|
||||
|
||||
with pytest.raises(ModelError):
|
||||
await Person2.objects.get()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_not_updated_model_m2m_raises_errors():
|
||||
Person3Ref = ForwardRef("Person3")
|
||||
|
||||
class PersonFriend(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
class Person3(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
supervisors: Person3Ref = ormar.ManyToMany(
|
||||
Person3Ref, through=PersonFriend, related_name="employees"
|
||||
)
|
||||
|
||||
with pytest.raises(ModelError):
|
||||
await Person3.objects.create(name="Test")
|
||||
|
||||
with pytest.raises(ModelError):
|
||||
Person3(name="Test")
|
||||
|
||||
with pytest.raises(ModelError):
|
||||
await Person3.objects.get()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_not_updated_model_m2m_through_raises_errors():
|
||||
PersonPetRef = ForwardRef("PersonPet")
|
||||
|
||||
class Pet(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
class Person4(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
pets: List[Pet] = ormar.ManyToMany(
|
||||
Pet, through=PersonPetRef, related_name="owners"
|
||||
)
|
||||
|
||||
class PersonPet(ormar.Model):
|
||||
class Meta(ModelMeta):
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
with pytest.raises(ModelError):
|
||||
await Person4.objects.create(name="Test")
|
||||
|
||||
with pytest.raises(ModelError):
|
||||
Person4(name="Test")
|
||||
|
||||
with pytest.raises(ModelError):
|
||||
await Person4.objects.get()
|
||||
|
||||
|
||||
def test_proper_field_init():
|
||||
assert "supervisor" in Person.Meta.model_fields
|
||||
assert Person.Meta.model_fields["supervisor"].to == Person
|
||||
|
||||
assert "supervisor" in Person.__fields__
|
||||
assert Person.__fields__["supervisor"].type_ == Person
|
||||
|
||||
assert "supervisor" in Person.Meta.table.columns
|
||||
assert isinstance(
|
||||
Person.Meta.table.columns["supervisor"].type, sa.sql.sqltypes.Integer
|
||||
)
|
||||
assert len(Person.Meta.table.columns["supervisor"].foreign_keys) > 0
|
||||
|
||||
assert "person_supervisor" in Person.Meta.alias_manager._aliases_new
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_self_relation():
|
||||
async with db:
|
||||
async with db.transaction(force_rollback=True):
|
||||
sam = await Person.objects.create(name="Sam")
|
||||
joe = await Person(name="Joe", supervisor=sam).save()
|
||||
assert joe.supervisor.name == "Sam"
|
||||
|
||||
joe_check = await Person.objects.select_related("supervisor").get(
|
||||
name="Joe"
|
||||
)
|
||||
assert joe_check.supervisor.name == "Sam"
|
||||
|
||||
sam_check = await Person.objects.select_related("employees").get(name="Sam")
|
||||
assert sam_check.name == "Sam"
|
||||
assert sam_check.employees[0].name == "Joe"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_other_forwardref_relation(cleanup):
|
||||
async with db:
|
||||
async with db.transaction(force_rollback=True):
|
||||
checkers = await Game.objects.create(name="checkers")
|
||||
uno = await Game(name="Uno").save()
|
||||
|
||||
await Child(
|
||||
name="Billy", favourite_game=uno, least_favourite_game=checkers
|
||||
).save()
|
||||
await Child(
|
||||
name="Kate", favourite_game=checkers, least_favourite_game=uno
|
||||
).save()
|
||||
|
||||
billy_check = await Child.objects.select_related(
|
||||
["favourite_game", "least_favourite_game"]
|
||||
).get(name="Billy")
|
||||
assert billy_check.favourite_game == uno
|
||||
assert billy_check.least_favourite_game == checkers
|
||||
|
||||
uno_check = await Game.objects.select_related(
|
||||
["liked_by", "not_liked_by"]
|
||||
).get(name="Uno")
|
||||
assert uno_check.liked_by[0].name == "Billy"
|
||||
assert uno_check.not_liked_by[0].name == "Kate"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_m2m_self_forwardref_relation(cleanup):
|
||||
async with db:
|
||||
async with db.transaction(force_rollback=True):
|
||||
checkers = await Game.objects.create(name="Checkers")
|
||||
uno = await Game(name="Uno").save()
|
||||
jenga = await Game(name="Jenga").save()
|
||||
|
||||
billy = await Child(
|
||||
name="Billy", favourite_game=uno, least_favourite_game=checkers
|
||||
).save()
|
||||
kate = await Child(
|
||||
name="Kate", favourite_game=checkers, least_favourite_game=uno
|
||||
).save()
|
||||
steve = await Child(
|
||||
name="Steve", favourite_game=jenga, least_favourite_game=uno
|
||||
).save()
|
||||
|
||||
await billy.friends.add(kate)
|
||||
await billy.friends.add(steve)
|
||||
|
||||
billy_check = await Child.objects.select_related(
|
||||
[
|
||||
"friends",
|
||||
"favourite_game",
|
||||
"least_favourite_game",
|
||||
"friends__favourite_game",
|
||||
"friends__least_favourite_game",
|
||||
]
|
||||
).get(name="Billy")
|
||||
assert len(billy_check.friends) == 2
|
||||
assert billy_check.friends[0].name == "Kate"
|
||||
assert billy_check.friends[0].favourite_game.name == "Checkers"
|
||||
assert billy_check.friends[0].least_favourite_game.name == "Uno"
|
||||
assert billy_check.friends[1].name == "Steve"
|
||||
assert billy_check.friends[1].favourite_game.name == "Jenga"
|
||||
assert billy_check.friends[1].least_favourite_game.name == "Uno"
|
||||
assert billy_check.favourite_game.name == "Uno"
|
||||
|
||||
kate_check = await Child.objects.select_related(["also_friends"]).get(
|
||||
name="Kate"
|
||||
)
|
||||
|
||||
assert len(kate_check.also_friends) == 1
|
||||
assert kate_check.also_friends[0].name == "Billy"
|
||||
|
||||
billy_check = (
|
||||
await Child.objects.select_related(
|
||||
[
|
||||
"friends",
|
||||
"favourite_game",
|
||||
"least_favourite_game",
|
||||
"friends__favourite_game",
|
||||
"friends__least_favourite_game",
|
||||
]
|
||||
)
|
||||
.filter(friends__favourite_game__name="Checkers")
|
||||
.get(name="Billy")
|
||||
)
|
||||
assert len(billy_check.friends) == 1
|
||||
assert billy_check.friends[0].name == "Kate"
|
||||
assert billy_check.friends[0].favourite_game.name == "Checkers"
|
||||
assert billy_check.friends[0].least_favourite_game.name == "Uno"
|
||||
166
tests/test_deferred/test_more_same_table_joins.py
Normal file
166
tests/test_deferred/test_more_same_table_joins.py
Normal file
@ -0,0 +1,166 @@
|
||||
import asyncio
|
||||
from typing import Optional
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
|
||||
|
||||
class Department(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "departments"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True, autoincrement=False)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class SchoolClass(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "schoolclasses"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "categories"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
department: Optional[Department] = ormar.ForeignKey(Department, nullable=False)
|
||||
|
||||
|
||||
class Student(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "students"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
schoolclass: Optional[SchoolClass] = ormar.ForeignKey(SchoolClass)
|
||||
category: Optional[Category] = ormar.ForeignKey(Category, nullable=True)
|
||||
|
||||
|
||||
class Teacher(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "teachers"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
schoolclass: Optional[SchoolClass] = ormar.ForeignKey(SchoolClass)
|
||||
category: Optional[Category] = ormar.ForeignKey(Category, nullable=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def event_loop():
|
||||
loop = asyncio.get_event_loop()
|
||||
yield loop
|
||||
loop.close()
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
async def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
|
||||
|
||||
async def create_data():
|
||||
department = await Department.objects.create(id=1, name="Math Department")
|
||||
department2 = await Department.objects.create(id=2, name="Law Department")
|
||||
class1 = await SchoolClass.objects.create(name="Math")
|
||||
class2 = await SchoolClass.objects.create(name="Logic")
|
||||
category = await Category.objects.create(name="Foreign", department=department)
|
||||
category2 = await Category.objects.create(name="Domestic", department=department2)
|
||||
await Student.objects.create(name="Jane", category=category, schoolclass=class1)
|
||||
await Student.objects.create(name="Judy", category=category2, schoolclass=class1)
|
||||
await Student.objects.create(name="Jack", category=category2, schoolclass=class2)
|
||||
await Teacher.objects.create(name="Joe", category=category2, schoolclass=class1)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_multiple_instances_of_same_table_in_schema():
|
||||
async with database:
|
||||
await create_data()
|
||||
classes = await SchoolClass.objects.select_related(
|
||||
["teachers__category__department", "students__category__department"]
|
||||
).all()
|
||||
assert classes[0].name == "Math"
|
||||
assert classes[0].students[0].name == "Jane"
|
||||
assert len(classes[0].dict().get("students")) == 2
|
||||
assert classes[0].teachers[0].category.department.name == "Law Department"
|
||||
assert classes[0].students[0].category.department.name == "Math Department"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_load_all_multiple_instances_of_same_table_in_schema():
|
||||
async with database:
|
||||
await create_data()
|
||||
math_class = await SchoolClass.objects.get(name="Math")
|
||||
assert math_class.name == "Math"
|
||||
|
||||
await math_class.load_all(follow=True)
|
||||
assert math_class.students[0].name == "Jane"
|
||||
assert len(math_class.dict().get("students")) == 2
|
||||
assert math_class.teachers[0].category.department.name == "Law Department"
|
||||
assert math_class.students[0].category.department.name == "Math Department"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_filter_groups_with_instances_of_same_table_in_schema():
|
||||
async with database:
|
||||
await create_data()
|
||||
math_class = (
|
||||
await SchoolClass.objects.select_related(
|
||||
["teachers__category__department", "students__category__department"]
|
||||
)
|
||||
.filter(
|
||||
ormar.or_(
|
||||
students__name="Jane",
|
||||
teachers__category__name="Domestic",
|
||||
students__category__name="Foreign",
|
||||
)
|
||||
)
|
||||
.get(name="Math")
|
||||
)
|
||||
assert math_class.name == "Math"
|
||||
assert math_class.students[0].name == "Jane"
|
||||
assert len(math_class.dict().get("students")) == 2
|
||||
assert math_class.teachers[0].category.department.name == "Law Department"
|
||||
assert math_class.students[0].category.department.name == "Math Department"
|
||||
|
||||
classes = (
|
||||
await SchoolClass.objects.select_related(
|
||||
["students__category__department", "teachers__category__department"]
|
||||
)
|
||||
.filter(
|
||||
ormar.and_(
|
||||
ormar.or_(
|
||||
students__name="Jane", students__category__name="Foreign"
|
||||
),
|
||||
teachers__category__department__name="Law Department",
|
||||
)
|
||||
)
|
||||
.all()
|
||||
)
|
||||
assert len(classes) == 1
|
||||
assert classes[0].teachers[0].category.department.name == "Law Department"
|
||||
assert classes[0].students[0].category.department.name == "Math Department"
|
||||
153
tests/test_deferred/test_same_table_joins.py
Normal file
153
tests/test_deferred/test_same_table_joins.py
Normal file
@ -0,0 +1,153 @@
|
||||
import asyncio
|
||||
from typing import Optional
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
|
||||
import ormar
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
metadata = sqlalchemy.MetaData()
|
||||
|
||||
|
||||
class Department(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "departments"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True, autoincrement=False)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class SchoolClass(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "schoolclasses"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
department: Optional[Department] = ormar.ForeignKey(Department, nullable=False)
|
||||
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "categories"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Student(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "students"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
schoolclass: Optional[SchoolClass] = ormar.ForeignKey(SchoolClass)
|
||||
category: Optional[Category] = ormar.ForeignKey(Category, nullable=True)
|
||||
|
||||
|
||||
class Teacher(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "teachers"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
schoolclass: Optional[SchoolClass] = ormar.ForeignKey(SchoolClass)
|
||||
category: Optional[Category] = ormar.ForeignKey(Category, nullable=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def event_loop():
|
||||
loop = asyncio.get_event_loop()
|
||||
yield loop
|
||||
loop.close()
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
async def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
metadata.drop_all(engine)
|
||||
metadata.create_all(engine)
|
||||
yield
|
||||
metadata.drop_all(engine)
|
||||
|
||||
|
||||
async def create_data():
|
||||
department = await Department.objects.create(id=1, name="Math Department")
|
||||
department2 = await Department.objects.create(id=2, name="Law Department")
|
||||
class1 = await SchoolClass.objects.create(name="Math", department=department)
|
||||
class2 = await SchoolClass.objects.create(name="Logic", department=department2)
|
||||
category = await Category.objects.create(name="Foreign")
|
||||
category2 = await Category.objects.create(name="Domestic")
|
||||
await Student.objects.create(name="Jane", category=category, schoolclass=class1)
|
||||
await Student.objects.create(name="Judy", category=category2, schoolclass=class1)
|
||||
await Student.objects.create(name="Jack", category=category2, schoolclass=class2)
|
||||
await Teacher.objects.create(name="Joe", category=category2, schoolclass=class1)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_multiple_instances_of_same_table_in_schema():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
await create_data()
|
||||
classes = await SchoolClass.objects.select_related(
|
||||
["teachers__category", "students__schoolclass"]
|
||||
).all()
|
||||
assert classes[0].name == "Math"
|
||||
assert classes[0].students[0].name == "Jane"
|
||||
|
||||
assert len(classes[0].dict().get("students")) == 2
|
||||
|
||||
# since it's going from schoolclass => teacher => schoolclass (same class) department is already populated
|
||||
assert classes[0].students[0].schoolclass.name == "Math"
|
||||
assert classes[0].students[0].schoolclass.department.name is None
|
||||
await classes[0].students[0].schoolclass.department.load()
|
||||
assert (
|
||||
classes[0].students[0].schoolclass.department.name == "Math Department"
|
||||
)
|
||||
|
||||
await classes[1].students[0].schoolclass.department.load()
|
||||
assert (
|
||||
classes[1].students[0].schoolclass.department.name == "Law Department"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_right_tables_join():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
await create_data()
|
||||
classes = await SchoolClass.objects.select_related(
|
||||
["teachers__category", "students"]
|
||||
).all()
|
||||
assert classes[0].teachers[0].category.name == "Domestic"
|
||||
|
||||
assert classes[0].students[0].category.name is None
|
||||
await classes[0].students[0].category.load()
|
||||
assert classes[0].students[0].category.name == "Foreign"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_multiple_reverse_related_objects():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
await create_data()
|
||||
classes = await SchoolClass.objects.select_related(
|
||||
["teachers__category", "students__category"]
|
||||
).all()
|
||||
assert classes[0].name == "Math"
|
||||
assert classes[0].students[1].name == "Judy"
|
||||
assert classes[0].students[0].category.name == "Foreign"
|
||||
assert classes[0].students[1].category.name == "Domestic"
|
||||
assert classes[0].teachers[0].category.name == "Domestic"
|
||||
Reference in New Issue
Block a user