Skip to content

Commit

Permalink
Merge pull request #12 from collerek/get_or_create
Browse files Browse the repository at this point in the history
add get/update or create queryset method and tests
  • Loading branch information
collerek authored Sep 24, 2020
2 parents 9f03482 + df3bb95 commit 3658d6a
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 1 deletion.
Binary file modified .coverage
Binary file not shown.
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,8 @@ await news.posts.clear()

```

Since version >=0.3.4 Ormar supports also queryset level delete and update statements
Since version >=0.3.4 Ormar supports also queryset level delete and update statements,
as well as get_or_create and update_or_create
```python
import databases
import ormar
Expand Down Expand Up @@ -308,6 +309,23 @@ await Book.objects.update(each=True, genre='Fiction')
all_books = await Book.objects.filter(genre='Fiction').all()
assert len(all_books) == 3

# helper get/update or create methods of queryset
# if not exists it will be created
vol1 = await Book.objects.get_or_create(title="Volume I", author='Anonymous', genre='Fiction')
assert await Book.objects.count() == 1

# if exists it will be returned
assert await Book.objects.get_or_create(title="Volume I", author='Anonymous', genre='Fiction') == vol1
assert await Book.objects.count() == 1

# 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

```

## Data types
Expand Down
15 changes: 15 additions & 0 deletions ormar/queryset/queryset.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,21 @@ async def get(self, **kwargs: Any) -> "Model":
self.check_single_result_rows_count(rows)
return rows[0]

async def get_or_create(self, **kwargs: Any) -> "Model":
try:
return await self.get(**kwargs)
except NoMatch:
return await self.create(**kwargs)

async def update_or_create(self, **kwargs: Any) -> "Model":
pk_name = self.model_cls.Meta.pkname
if "pk" in kwargs:
kwargs[pk_name] = kwargs.pop("pk")
if pk_name not in kwargs or kwargs.get(pk_name) is None:
return await self.create(**kwargs)
model = await self.get(pk=kwargs[pk_name])
return await model.update(**kwargs)

async def all(self, **kwargs: Any) -> List["Model"]: # noqa: A003
if kwargs:
return await self.filter(**kwargs).all()
Expand Down
31 changes: 31 additions & 0 deletions tests/test_queryset_level_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,34 @@ async def test_delete_and_update():
await Book.objects.delete(each=True)
all_books = await Book.objects.all()
assert len(all_books) == 0


@pytest.mark.asyncio
async def test_get_or_create():
async with database:
tom = await Book.objects.get_or_create(title="Volume I", author='Anonymous', genre='Fiction')
assert await Book.objects.count() == 1

assert await Book.objects.get_or_create(title="Volume I", author='Anonymous', genre='Fiction') == tom
assert await Book.objects.count() == 1

assert await Book.objects.create(title="Volume I", author='Anonymous', genre='Fiction')
with pytest.raises(ormar.exceptions.MultipleMatches):
await Book.objects.get_or_create(title="Volume I", author='Anonymous', genre='Fiction')


@pytest.mark.asyncio
async def test_update_or_create():
async with database:
tom = await Book.objects.update_or_create(title="Volume I", author='Anonymous', genre='Fiction')
assert await Book.objects.count() == 1

assert await Book.objects.update_or_create(id=tom.id, genre='Historic')
assert await Book.objects.count() == 1

assert await Book.objects.update_or_create(pk=tom.id, genre='Fantasy')
assert await Book.objects.count() == 1

assert await Book.objects.create(title="Volume I", author='Anonymous', genre='Fantasy')
with pytest.raises(ormar.exceptions.MultipleMatches):
await Book.objects.get(title="Volume I", author='Anonymous', genre='Fantasy')

0 comments on commit 3658d6a

Please sign in to comment.