change limit/offset with select related to be applied on a subquery and limit only main model query

This commit is contained in:
collerek
2020-12-21 18:42:17 +01:00
parent 514e8c4ad5
commit c8aad2385c
18 changed files with 329 additions and 69 deletions

View File

@ -89,6 +89,10 @@ async def test_working_with_aliases():
first_name="Son", last_name="2", born_year=1995
)
await artist.children.create(
first_name="Son", last_name="3", born_year=1998
)
album = await Album.objects.select_related("artist").first()
assert album.artist.last_name == "Mosbey"
@ -99,9 +103,10 @@ async def test_working_with_aliases():
assert album.name == "Aunt Robin"
artist = await Artist.objects.select_related("children").get()
assert len(artist.children) == 2
assert len(artist.children) == 3
assert artist.children[0].first_name == "Son"
assert artist.children[1].last_name == "2"
assert artist.children[2].last_name == "3"
await artist.update(last_name="Bundy")
await Artist.objects.filter(pk=artist.pk).update(born_year=1974)

View File

@ -205,11 +205,11 @@ async def test_model_removal_from_relations():
album = await Album.objects.select_related("tracks").get(name="Chichi")
assert track1.album == album
track1.remove(album)
track1.remove(album, name="album")
assert track1.album is None
assert len(album.tracks) == 2
track2.remove(album)
track2.remove(album, name="album")
assert track2.album is None
assert len(album.tracks) == 1

View File

@ -102,6 +102,7 @@ class Car(ormar.Model):
name: str = ormar.String(max_length=50)
owner: Person = ormar.ForeignKey(Person)
co_owner: Person = ormar.ForeignKey(Person, related_name="coowned")
created_date: datetime.datetime = ormar.DateTime(default=datetime.datetime.now)
class Truck(Car):
@ -291,11 +292,22 @@ async def test_inheritance_with_relation():
).get(name="Joe")
assert joe_check.pk == joe.pk
assert joe_check.coowned_trucks[0] == shelby
assert joe_check.coowned_trucks[0].created_date is not None
assert joe_check.coowned_buses[0] == unicorn
assert joe_check.coowned_buses[0].created_date is not None
joe_check = await Person.objects.prefetch_related(
["coowned_trucks", "coowned_buses"]
).get(name="Joe")
joe_check = (
await Person.objects.exclude_fields(
{
"coowned_trucks": {"created_date"},
"coowned_buses": {"created_date"},
}
)
.prefetch_related(["coowned_trucks", "coowned_buses"])
.get(name="Joe")
)
assert joe_check.pk == joe.pk
assert joe_check.coowned_trucks[0] == shelby
assert joe_check.coowned_trucks[0].created_date is None
assert joe_check.coowned_buses[0] == unicorn
assert joe_check.coowned_buses[0].created_date is None

View File

@ -58,6 +58,16 @@ class User(ormar.Model):
name: str = ormar.String(max_length=100, default="")
class User2(ormar.Model):
class Meta:
tablename = "users2"
metadata = metadata
database = database
id: str = ormar.String(primary_key=True, max_length=100)
name: str = ormar.String(max_length=100, default="")
class Product(ormar.Model):
class Meta:
tablename = "product"
@ -215,8 +225,9 @@ async def test_model_get():
assert lookup == user
user = await User.objects.create(name="Jane")
await User.objects.create(name="Jane")
with pytest.raises(ormar.MultipleMatches):
await User.objects.get()
await User.objects.get(name="Jane")
same_user = await User.objects.get(pk=user.id)
assert same_user.id == user.id
@ -467,3 +478,32 @@ async def test_start_and_end_filters():
users = await User.objects.filter(name__endswith="igo").all()
assert len(users) == 2
@pytest.mark.asyncio
async def test_get_and_first():
async with database:
async with database.transaction(force_rollback=True):
await User.objects.create(name="Tom")
await User.objects.create(name="Jane")
await User.objects.create(name="Lucy")
await User.objects.create(name="Zack")
await User.objects.create(name="Ula")
user = await User.objects.get()
assert user.name == "Ula"
user = await User.objects.first()
assert user.name == "Tom"
await User2.objects.create(id="Tom", name="Tom")
await User2.objects.create(id="Jane", name="Jane")
await User2.objects.create(id="Lucy", name="Lucy")
await User2.objects.create(id="Zack", name="Zack")
await User2.objects.create(id="Ula", name="Ula")
user = await User2.objects.get()
assert user.name == "Zack"
user = await User2.objects.first()
assert user.name == "Jane"

View File

@ -266,7 +266,7 @@ async def test_prefetch_related_with_select_related():
await Album.objects.select_related(["tracks", "shops"])
.filter(name="Malibu")
.prefetch_related(["cover_pictures", "shops__division"])
.get()
.first()
)
assert len(album.tracks) == 0

View File

@ -90,14 +90,65 @@ async def test_create_primary_models():
await p1.keywords.add(keyword)
else:
await p2.keywords.add(keyword)
models = await PrimaryModel.objects.prefetch_related("keywords").limit(5).all()
models = await PrimaryModel.objects.select_related("keywords").limit(5).all()
# This test fails, because of the keywords relation.
assert len(models) == 5
assert len(models[0].keywords) == 2
assert len(models[1].keywords) == 3
assert len(models[2].keywords) == 0
models2 = (
await PrimaryModel.objects.select_related("keywords")
.limit(5)
.offset(3)
.all()
)
assert len(models2) == 5
assert [x.name for x in models2] != [x.name for x in models]
assert [x.name for x in models2] == [
"Primary 4",
"Primary 5",
"Primary 6",
"Primary 7",
"Primary 8",
]
models3 = (
await PrimaryModel.objects.select_related("keywords")
.limit(5, limit_raw_sql=True)
.all()
)
assert len(models3) == 2
assert len(models3[0].keywords) == 2
assert len(models3[1].keywords) == 3
models4 = (
await PrimaryModel.objects.offset(1)
.select_related("keywords")
.limit(5, limit_raw_sql=True)
.all()
)
assert len(models4) == 3
assert [x.name for x in models4] == ["Primary 1", "Primary 2", "Primary 3"]
assert len(models4[0].keywords) == 1
assert len(models4[1].keywords) == 3
assert len(models4[2].keywords) == 0
models5 = (
await PrimaryModel.objects.select_related("keywords")
.offset(2, limit_raw_sql=True)
.limit(5)
.all()
)
assert len(models5) == 3
assert [x.name for x in models5] == ["Primary 2", "Primary 3", "Primary 4"]
assert len(models5[0].keywords) == 3
assert len(models5[1].keywords) == 0
assert len(models5[2].keywords) == 0
@pytest.fixture(autouse=True, scope="module")
def create_test_database():