Add QuerySet.first_or_none (#1137)

* Add QuerySet.first_or_none

* restore docstrings for exceptions

---------

Co-authored-by: collerek <collerek@gmail.com>
This commit is contained in:
Dominik Kozaczko
2024-05-26 20:13:41 +02:00
committed by GitHub
parent 1a22cf3a31
commit a6462a0ab9
2 changed files with 27 additions and 1 deletions

View File

@ -933,6 +933,23 @@ class QuerySet(Generic[T]):
self.check_single_result_rows_count(processed_rows)
return processed_rows[0] # type: ignore
async def first_or_none(self, *args: Any, **kwargs: Any) -> Optional["T"]:
"""
Gets the first row from the db ordered by primary key column ascending.
If no match is found None will be returned.
:raises MultipleMatches: if more than 1 row is returned.
:param kwargs: fields names and proper value types
:type kwargs: Any
:return: returned model
:rtype: Model
"""
try:
return await self.first(*args, **kwargs)
except ormar.NoMatch:
return None
async def get_or_none(self, *args: Any, **kwargs: Any) -> Optional["T"]:
"""
Gets the first row from the db meeting the criteria set by kwargs.
@ -942,8 +959,9 @@ class QuerySet(Generic[T]):
Passing a criteria is actually calling filter(*args, **kwargs) method described
below.
If not match is found None will be returned.
If no match is found None will be returned.
:raises MultipleMatches: if more than 1 row is returned.
:param kwargs: fields names and proper value types
:type kwargs: Any
:return: returned model

View File

@ -451,6 +451,11 @@ async def test_offset():
async def test_model_first():
async with base_ormar_config.database:
async with base_ormar_config.database.transaction(force_rollback=True):
with pytest.raises(ormar.NoMatch):
await User.objects.first()
assert await User.objects.first_or_none() is None
tom = await User.objects.create(name="Tom")
jane = await User.objects.create(name="Jane")
@ -460,6 +465,9 @@ async def test_model_first():
with pytest.raises(NoMatch):
await User.objects.filter(name="Lucy").first()
assert await User.objects.first_or_none(name="Lucy") is None
assert await User.objects.filter(name="Lucy").first_or_none() is None
assert await User.objects.order_by("name").first() == jane