diff --git a/docs/making_queries.md b/docs/making_queries.md index 1e3c0e2..cfb13a1 100644 --- a/docs/making_queries.md +++ b/docs/making_queries.md @@ -140,6 +140,14 @@ await Note.objects.order_by("id").limit(1).offset(1).all() await Note.objects.filter(text__icontains="mum").limit(2).all() ``` +#### .exists() + +To check if any instances matching the query exist. Returns `True` or `False`. + +```python +await Note.objects.filter(completed=True).exists() +``` + ### Updating instances `.update()` method is defined on model instances. @@ -169,3 +177,16 @@ Then delete the instance: ```python await note.delete() ``` + +### Convenience methods + +#### get_or_create() + +To get an existing instance matching the query, or create a new one. +This will retuurn a tuple of `instance` and `created`. + +```python +note, created = await Note.objects.get_or_create(text="Going to car wash") +``` + +**Note**: Since this is doing a [get()](#get), it can raise `MultipleMatches` exception. diff --git a/orm/models.py b/orm/models.py index cc83358..2b15db9 100644 --- a/orm/models.py +++ b/orm/models.py @@ -305,6 +305,14 @@ async def create(self, **kwargs): instance.pk = await self.database.execute(expr) return instance + async def get_or_create(self, **kwargs) -> typing.Tuple[typing.Any, bool]: + try: + instance = await self.get(**kwargs) + return instance, False + except NoMatch: + instance = await self.create(**kwargs) + return instance, True + def _prepare_order_by(self, order_by: str): reverse = order_by.startswith("-") order_by = order_by.lstrip("-") diff --git a/tests/test_models.py b/tests/test_models.py index 894ae42..ade2678 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -246,3 +246,14 @@ async def test_model_first(): assert await User.objects.first(name="Jane") == jane assert await User.objects.filter(name="Jane").first() == jane assert await User.objects.filter(name="Lucy").first() is None + + +async def test_model_get_or_create(): + async with database: + user, created = await User.objects.get_or_create(name="Tom") + + assert created is True + assert await User.objects.get(pk=user.id) == user + + user, created = await User.objects.get_or_create(name="Tom") + assert created is False