Merge pull request #557 from MojixCoder/master
Update get_or_create method
This commit is contained in:
@ -587,7 +587,7 @@ metadata.drop_all(engine)
|
|||||||
* `create(**kwargs): -> Model`
|
* `create(**kwargs): -> Model`
|
||||||
* `get(*args, **kwargs): -> Model`
|
* `get(*args, **kwargs): -> Model`
|
||||||
* `get_or_none(*args, **kwargs): -> Optional[Model]`
|
* `get_or_none(*args, **kwargs): -> Optional[Model]`
|
||||||
* `get_or_create(*args, **kwargs) -> Model`
|
* `get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs) -> Tuple[Model, bool]`
|
||||||
* `first(*args, **kwargs): -> Model`
|
* `first(*args, **kwargs): -> Model`
|
||||||
* `update(each: bool = False, **kwargs) -> int`
|
* `update(each: bool = False, **kwargs) -> int`
|
||||||
* `update_or_create(**kwargs) -> Model`
|
* `update_or_create(**kwargs) -> Model`
|
||||||
|
|||||||
@ -753,7 +753,7 @@ below.
|
|||||||
#### get\_or\_create
|
#### get\_or\_create
|
||||||
|
|
||||||
```python
|
```python
|
||||||
| async get_or_create(*args: Any, **kwargs: Any) -> "T"
|
| async get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args: Any, **kwargs: Any) -> Tuple["T", bool]
|
||||||
```
|
```
|
||||||
|
|
||||||
Combination of create and get methods.
|
Combination of create and get methods.
|
||||||
|
|||||||
@ -404,7 +404,7 @@ each=True flag to affect whole table.
|
|||||||
#### get\_or\_create
|
#### get\_or\_create
|
||||||
|
|
||||||
```python
|
```python
|
||||||
| async get_or_create(*args: Any, **kwargs: Any) -> "T"
|
| async get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args: Any, **kwargs: Any) -> Tuple["T", bool]
|
||||||
```
|
```
|
||||||
|
|
||||||
Combination of create and get methods.
|
Combination of create and get methods.
|
||||||
|
|||||||
@ -596,7 +596,7 @@ metadata.drop_all(engine)
|
|||||||
* `create(**kwargs): -> Model`
|
* `create(**kwargs): -> Model`
|
||||||
* `get(*args, **kwargs): -> Model`
|
* `get(*args, **kwargs): -> Model`
|
||||||
* `get_or_none(*args, **kwargs): -> Optional[Model]`
|
* `get_or_none(*args, **kwargs): -> Optional[Model]`
|
||||||
* `get_or_create(*args, **kwargs) -> Model`
|
* `get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs) -> Tuple[Model, bool]`
|
||||||
* `first(*args, **kwargs): -> Model`
|
* `first(*args, **kwargs): -> Model`
|
||||||
* `update(each: bool = False, **kwargs) -> int`
|
* `update(each: bool = False, **kwargs) -> int`
|
||||||
* `update_or_create(**kwargs) -> Model`
|
* `update_or_create(**kwargs) -> Model`
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
Following methods allow you to insert data into the database.
|
Following methods allow you to insert data into the database.
|
||||||
|
|
||||||
* `create(**kwargs) -> Model`
|
* `create(**kwargs) -> Model`
|
||||||
* `get_or_create(**kwargs) -> Model`
|
* `get_or_create(_defaults: Optional[Dict[str, Any]] = None, **kwargs) -> Tuple[Model, bool]`
|
||||||
* `update_or_create(**kwargs) -> Model`
|
* `update_or_create(**kwargs) -> Model`
|
||||||
* `bulk_create(objects: List[Model]) -> None`
|
* `bulk_create(objects: List[Model]) -> None`
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ Following methods allow you to insert data into the database.
|
|||||||
|
|
||||||
* `QuerysetProxy`
|
* `QuerysetProxy`
|
||||||
* `QuerysetProxy.create(**kwargs)` method
|
* `QuerysetProxy.create(**kwargs)` method
|
||||||
* `QuerysetProxy.get_or_create(**kwargs)` method
|
* `QuerysetProxy.get_or_create(_defaults: Optional[Dict[str, Any]] = None, **kwargs)` method
|
||||||
* `QuerysetProxy.update_or_create(**kwargs)` method
|
* `QuerysetProxy.update_or_create(**kwargs)` method
|
||||||
|
|
||||||
## create
|
## create
|
||||||
@ -56,12 +56,15 @@ await malibu.save()
|
|||||||
|
|
||||||
## get_or_create
|
## get_or_create
|
||||||
|
|
||||||
`get_or_create(**kwargs) -> Model`
|
`get_or_create(_defaults: Optional[Dict[str, Any]] = None, **kwargs) -> Tuple[Model, bool]`
|
||||||
|
|
||||||
Combination of create and get methods.
|
Combination of create and get methods.
|
||||||
|
|
||||||
Tries to get a row meeting the criteria and if `NoMatch` exception is raised it creates
|
Tries to get a row meeting the criteria and if `NoMatch` exception is raised it creates
|
||||||
a new one with given kwargs.
|
a new one with given kwargs and _defaults.
|
||||||
|
|
||||||
|
When `_defaults` dictionary is provided the values set in `_defaults` will **always** be set, including overwriting explicitly provided values.
|
||||||
|
i.e. `get_or_create(_defaults: {"title": "I win"}, title="never used")` will always use "I win" as title whether you provide your own value in kwargs or not.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
class Album(ormar.Model):
|
class Album(ormar.Model):
|
||||||
@ -72,12 +75,17 @@ class Album(ormar.Model):
|
|||||||
|
|
||||||
id: int = ormar.Integer(primary_key=True)
|
id: int = ormar.Integer(primary_key=True)
|
||||||
name: str = ormar.String(max_length=100)
|
name: str = ormar.String(max_length=100)
|
||||||
|
year: int = ormar.Integer()
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
album = await Album.objects.get_or_create(name='The Cat')
|
album, created = await Album.objects.get_or_create(name='The Cat', _defaults={"year": 1999})
|
||||||
|
assert created is True
|
||||||
|
assert album.name == "The Cat"
|
||||||
|
assert album.year == 1999
|
||||||
# object is created as it does not exist
|
# object is created as it does not exist
|
||||||
album2 = await Album.objects.get_or_create(name='The Cat')
|
album2, created = await Album.objects.get_or_create(name='The Cat')
|
||||||
|
assert created is False
|
||||||
assert album == album2
|
assert album == album2
|
||||||
# return True as the same db row is returned
|
# return True as the same db row is returned
|
||||||
```
|
```
|
||||||
|
|||||||
@ -6,7 +6,7 @@ You can use following methods to filter the data (sql where clause).
|
|||||||
* `exclude(*args, **kwargs) -> QuerySet`
|
* `exclude(*args, **kwargs) -> QuerySet`
|
||||||
* `get(*args, **kwargs) -> Model`
|
* `get(*args, **kwargs) -> Model`
|
||||||
* `get_or_none(*args, **kwargs) -> Optional[Model]`
|
* `get_or_none(*args, **kwargs) -> Optional[Model]`
|
||||||
* `get_or_create(*args, **kwargs) -> Model`
|
* `get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs) -> Tuple[Model, bool]`
|
||||||
* `all(*args, **kwargs) -> List[Optional[Model]]`
|
* `all(*args, **kwargs) -> List[Optional[Model]]`
|
||||||
|
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ You can use following methods to filter the data (sql where clause).
|
|||||||
* `QuerysetProxy.exclude(*args, **kwargs)` method
|
* `QuerysetProxy.exclude(*args, **kwargs)` method
|
||||||
* `QuerysetProxy.get(*args, **kwargs)` method
|
* `QuerysetProxy.get(*args, **kwargs)` method
|
||||||
* `QuerysetProxy.get_or_none(*args, **kwargs)` method
|
* `QuerysetProxy.get_or_none(*args, **kwargs)` method
|
||||||
* `QuerysetProxy.get_or_create(*args, **kwargs)` method
|
* `QuerysetProxy.get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs)` method
|
||||||
* `QuerysetProxy.all(*args, **kwargs)` method
|
* `QuerysetProxy.all(*args, **kwargs)` method
|
||||||
|
|
||||||
And following methods to sort the data (sql order by clause).
|
And following methods to sort the data (sql order by clause).
|
||||||
@ -598,7 +598,7 @@ Exact equivalent of get described above but instead of raising the exception ret
|
|||||||
|
|
||||||
## get_or_create
|
## get_or_create
|
||||||
|
|
||||||
`get_or_create(*args, **kwargs) -> Model`
|
`get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs) -> Tuple[Model, bool]`
|
||||||
|
|
||||||
Combination of create and get methods.
|
Combination of create and get methods.
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ To read more about any specific section or function please refer to the details
|
|||||||
###[Insert data into database](./create.md)
|
###[Insert data into database](./create.md)
|
||||||
|
|
||||||
* `create(**kwargs) -> Model`
|
* `create(**kwargs) -> Model`
|
||||||
* `get_or_create(**kwargs) -> Model`
|
* `get_or_create(_defaults: Optional[Dict[str, Any]] = None, **kwargs) -> Tuple[Model, bool]`
|
||||||
* `update_or_create(**kwargs) -> Model`
|
* `update_or_create(**kwargs) -> Model`
|
||||||
* `bulk_create(objects: List[Model]) -> None`
|
* `bulk_create(objects: List[Model]) -> None`
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ To read more about any specific section or function please refer to the details
|
|||||||
|
|
||||||
* `QuerysetProxy`
|
* `QuerysetProxy`
|
||||||
* `QuerysetProxy.create(**kwargs)` method
|
* `QuerysetProxy.create(**kwargs)` method
|
||||||
* `QuerysetProxy.get_or_create(**kwargs)` method
|
* `QuerysetProxy.get_or_create(_defaults: Optional[Dict[str, Any]] = None, **kwargs)` method
|
||||||
* `QuerysetProxy.update_or_create(**kwargs)` method
|
* `QuerysetProxy.update_or_create(**kwargs)` method
|
||||||
|
|
||||||
!!!tip
|
!!!tip
|
||||||
@ -47,7 +47,7 @@ To read more about any specific section or function please refer to the details
|
|||||||
|
|
||||||
* `get(**kwargs) -> Model`
|
* `get(**kwargs) -> Model`
|
||||||
* `get_or_none(**kwargs) -> Optional[Model]`
|
* `get_or_none(**kwargs) -> Optional[Model]`
|
||||||
* `get_or_create(**kwargs) -> Model`
|
* `get_or_create(_defaults: Optional[Dict[str, Any]] = None, **kwargs) -> Tuple[Model, bool]`
|
||||||
* `first() -> Model`
|
* `first() -> Model`
|
||||||
* `all(**kwargs) -> List[Optional[Model]]`
|
* `all(**kwargs) -> List[Optional[Model]]`
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ To read more about any specific section or function please refer to the details
|
|||||||
* `QuerysetProxy`
|
* `QuerysetProxy`
|
||||||
* `QuerysetProxy.get(**kwargs)` method
|
* `QuerysetProxy.get(**kwargs)` method
|
||||||
* `QuerysetProxy.get_or_none(**kwargs)` method
|
* `QuerysetProxy.get_or_none(**kwargs)` method
|
||||||
* `QuerysetProxy.get_or_create(**kwargs)` method
|
* `QuerysetProxy.get_or_create(_defaults: Optional[Dict[str, Any]] = None, **kwargs)` method
|
||||||
* `QuerysetProxy.first()` method
|
* `QuerysetProxy.first()` method
|
||||||
* `QuerysetProxy.all(**kwargs)` method
|
* `QuerysetProxy.all(**kwargs)` method
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ Instead of ormar models return raw data in form list of dictionaries or tuples.
|
|||||||
* `order_by(columns:Union[List, str]) -> QuerySet`
|
* `order_by(columns:Union[List, str]) -> QuerySet`
|
||||||
* `get(**kwargs) -> Model`
|
* `get(**kwargs) -> Model`
|
||||||
* `get_or_none(**kwargs) -> Optional[Model]`
|
* `get_or_none(**kwargs) -> Optional[Model]`
|
||||||
* `get_or_create(**kwargs) -> Model`
|
* `get_or_create(_defaults: Optional[Dict[str, Any]] = None, **kwargs) -> Tuple[Model, bool]`
|
||||||
* `all(**kwargs) -> List[Optional[Model]]`
|
* `all(**kwargs) -> List[Optional[Model]]`
|
||||||
|
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ Instead of ormar models return raw data in form list of dictionaries or tuples.
|
|||||||
* `QuerysetProxy.order_by(columns:Union[List, str])` method
|
* `QuerysetProxy.order_by(columns:Union[List, str])` method
|
||||||
* `QuerysetProxy.get(**kwargs)` method
|
* `QuerysetProxy.get(**kwargs)` method
|
||||||
* `QuerysetProxy.get_or_none(**kwargs)` method
|
* `QuerysetProxy.get_or_none(**kwargs)` method
|
||||||
* `QuerysetProxy.get_or_create(**kwargs)` method
|
* `QuerysetProxy.get_or_create(_defaults: Optional[Dict[str, Any]] = None, **kwargs)` method
|
||||||
* `QuerysetProxy.all(**kwargs)` method
|
* `QuerysetProxy.all(**kwargs)` method
|
||||||
|
|
||||||
!!!tip
|
!!!tip
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
Following methods allow you to load data from the database.
|
Following methods allow you to load data from the database.
|
||||||
|
|
||||||
* `get(*args, **kwargs) -> Model`
|
* `get(*args, **kwargs) -> Model`
|
||||||
* `get_or_create(*args, **kwargs) -> Model`
|
* `get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs) -> Tuple[Model, bool]`
|
||||||
* `first(*args, **kwargs) -> Model`
|
* `first(*args, **kwargs) -> Model`
|
||||||
* `all(*args, **kwargs) -> List[Optional[Model]]`
|
* `all(*args, **kwargs) -> List[Optional[Model]]`
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ Following methods allow you to load data from the database.
|
|||||||
|
|
||||||
* `QuerysetProxy`
|
* `QuerysetProxy`
|
||||||
* `QuerysetProxy.get(*args, **kwargs)` method
|
* `QuerysetProxy.get(*args, **kwargs)` method
|
||||||
* `QuerysetProxy.get_or_create(*args, **kwargs)` method
|
* `QuerysetProxy.get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs)` method
|
||||||
* `QuerysetProxy.first(*args, **kwargs)` method
|
* `QuerysetProxy.first(*args, **kwargs)` method
|
||||||
* `QuerysetProxy.all(*args, **kwargs)` method
|
* `QuerysetProxy.all(*args, **kwargs)` method
|
||||||
|
|
||||||
@ -64,12 +64,12 @@ Exact equivalent of get described above but instead of raising the exception ret
|
|||||||
|
|
||||||
## get_or_create
|
## get_or_create
|
||||||
|
|
||||||
`get_or_create(*args, **kwargs) -> Model`
|
`get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs) -> Tuple[Model, bool]`
|
||||||
|
|
||||||
Combination of create and get methods.
|
Combination of create and get methods.
|
||||||
|
|
||||||
Tries to get a row meeting the criteria and if `NoMatch` exception is raised it creates
|
Tries to get a row meeting the criteria and if `NoMatch` exception is raised it creates
|
||||||
a new one with given kwargs.
|
a new one with given kwargs and _defaults.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
class Album(ormar.Model):
|
class Album(ormar.Model):
|
||||||
@ -80,12 +80,17 @@ class Album(ormar.Model):
|
|||||||
|
|
||||||
id: int = ormar.Integer(primary_key=True)
|
id: int = ormar.Integer(primary_key=True)
|
||||||
name: str = ormar.String(max_length=100)
|
name: str = ormar.String(max_length=100)
|
||||||
|
year: int = ormar.Integer()
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
album = await Album.objects.get_or_create(name='The Cat')
|
album, created = await Album.objects.get_or_create(name='The Cat', _defaults={"year": 1999})
|
||||||
|
assert created is True
|
||||||
|
assert album.name == "The Cat"
|
||||||
|
assert album.year == 1999
|
||||||
# object is created as it does not exist
|
# object is created as it does not exist
|
||||||
album2 = await Album.objects.get_or_create(name='The Cat')
|
album2, created = await Album.objects.get_or_create(name='The Cat')
|
||||||
|
assert created is False
|
||||||
assert album == album2
|
assert album == album2
|
||||||
# return True as the same db row is returned
|
# return True as the same db row is returned
|
||||||
```
|
```
|
||||||
|
|||||||
@ -56,9 +56,9 @@ assert post.categories[0] == news
|
|||||||
|
|
||||||
### get_or_create
|
### get_or_create
|
||||||
|
|
||||||
`get_or_create(**kwargs) -> Model`
|
`get_or_create(_defaults: Optional[Dict[str, Any]] = None, **kwargs) -> Tuple[Model, bool]`
|
||||||
|
|
||||||
Tries to get a row meeting the criteria and if NoMatch exception is raised it creates a new one with given kwargs.
|
Tries to get a row meeting the criteria and if NoMatch exception is raised it creates a new one with given kwargs and _defaults.
|
||||||
|
|
||||||
!!!tip
|
!!!tip
|
||||||
Read more in queries documentation [get_or_create][get_or_create]
|
Read more in queries documentation [get_or_create][get_or_create]
|
||||||
@ -129,7 +129,7 @@ await post.categories.create(
|
|||||||
|
|
||||||
### get_or_create
|
### get_or_create
|
||||||
|
|
||||||
`get_or_create(**kwargs) -> Model`
|
`get_or_create(_defaults: Optional[Dict[str, Any]] = None, **kwargs) -> Tuple[Model, bool]`
|
||||||
|
|
||||||
Tries to get a row meeting the criteria and if NoMatch exception is raised it creates a new one with given kwargs.
|
Tries to get a row meeting the criteria and if NoMatch exception is raised it creates a new one with given kwargs.
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from typing import Any, Dict, List, Optional, Sequence, Set, TYPE_CHECKING, Union
|
from typing import Any, Dict, List, Optional, Sequence, Set, TYPE_CHECKING, Tuple, Union
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from typing import Protocol
|
from typing import Protocol
|
||||||
@ -55,7 +55,11 @@ class QuerySetProtocol(Protocol): # pragma: nocover
|
|||||||
async def update(self, each: bool = False, **kwargs: Any) -> int:
|
async def update(self, each: bool = False, **kwargs: Any) -> int:
|
||||||
...
|
...
|
||||||
|
|
||||||
async def get_or_create(self, **kwargs: Any) -> "Model":
|
async def get_or_create(
|
||||||
|
self,
|
||||||
|
_defaults: Optional[Dict[str, Any]] = None,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> Tuple["Model", bool]:
|
||||||
...
|
...
|
||||||
|
|
||||||
async def update_or_create(self, **kwargs: Any) -> "Model":
|
async def update_or_create(self, **kwargs: Any) -> "Model":
|
||||||
|
|||||||
@ -981,26 +981,34 @@ class QuerySet(Generic[T]):
|
|||||||
self.check_single_result_rows_count(processed_rows)
|
self.check_single_result_rows_count(processed_rows)
|
||||||
return processed_rows[0] # type: ignore
|
return processed_rows[0] # type: ignore
|
||||||
|
|
||||||
async def get_or_create(self, *args: Any, **kwargs: Any) -> "T":
|
async def get_or_create(
|
||||||
|
self,
|
||||||
|
_defaults: Optional[Dict[str, Any]] = None,
|
||||||
|
*args: Any,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> Tuple["T", bool]:
|
||||||
"""
|
"""
|
||||||
Combination of create and get methods.
|
Combination of create and get methods.
|
||||||
|
|
||||||
Tries to get a row meeting the criteria for kwargs
|
Tries to get a row meeting the criteria for kwargs
|
||||||
and if `NoMatch` exception is raised
|
and if `NoMatch` exception is raised
|
||||||
it creates a new one with given kwargs.
|
it creates a new one with given kwargs and _defaults.
|
||||||
|
|
||||||
Passing a criteria is actually calling filter(*args, **kwargs) method described
|
Passing a criteria is actually calling filter(*args, **kwargs) method described
|
||||||
below.
|
below.
|
||||||
|
|
||||||
:param kwargs: fields names and proper value types
|
:param kwargs: fields names and proper value types
|
||||||
:type kwargs: Any
|
:type kwargs: Any
|
||||||
:return: returned or created Model
|
:param _defaults: default values for creating object
|
||||||
:rtype: Model
|
:type _defaults: Optional[Dict[str, Any]]
|
||||||
|
:return: model instance and a boolean
|
||||||
|
:rtype: Tuple("T", bool)
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return await self.get(*args, **kwargs)
|
return await self.get(*args, **kwargs), False
|
||||||
except NoMatch:
|
except NoMatch:
|
||||||
return await self.create(**kwargs)
|
_defaults = _defaults or {}
|
||||||
|
return await self.create(**{**kwargs, **_defaults}), True
|
||||||
|
|
||||||
async def update_or_create(self, **kwargs: Any) -> "T":
|
async def update_or_create(self, **kwargs: Any) -> "T":
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -9,6 +9,7 @@ from typing import ( # noqa: I100, I201
|
|||||||
Sequence,
|
Sequence,
|
||||||
Set,
|
Set,
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
|
Tuple,
|
||||||
Type,
|
Type,
|
||||||
TypeVar,
|
TypeVar,
|
||||||
Union,
|
Union,
|
||||||
@ -488,23 +489,31 @@ class QuerysetProxy(Generic[T]):
|
|||||||
)
|
)
|
||||||
return len(children)
|
return len(children)
|
||||||
|
|
||||||
async def get_or_create(self, *args: Any, **kwargs: Any) -> "T":
|
async def get_or_create(
|
||||||
|
self,
|
||||||
|
_defaults: Optional[Dict[str, Any]] = None,
|
||||||
|
*args: Any,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> Tuple["T", bool]:
|
||||||
"""
|
"""
|
||||||
Combination of create and get methods.
|
Combination of create and get methods.
|
||||||
|
|
||||||
Tries to get a row meeting the criteria fro kwargs
|
Tries to get a row meeting the criteria fro kwargs
|
||||||
and if `NoMatch` exception is raised
|
and if `NoMatch` exception is raised
|
||||||
it creates a new one with given kwargs.
|
it creates a new one with given kwargs and _defaults.
|
||||||
|
|
||||||
:param kwargs: fields names and proper value types
|
:param kwargs: fields names and proper value types
|
||||||
:type kwargs: Any
|
:type kwargs: Any
|
||||||
:return: returned or created Model
|
:param _defaults: default values for creating object
|
||||||
:rtype: Model
|
:type _defaults: Optional[Dict[str, Any]]
|
||||||
|
:return: model instance and a boolean
|
||||||
|
:rtype: Tuple("T", bool)
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return await self.get(*args, **kwargs)
|
return await self.get(*args, **kwargs), False
|
||||||
except ormar.NoMatch:
|
except NoMatch:
|
||||||
return await self.create(**kwargs)
|
_defaults = _defaults or {}
|
||||||
|
return await self.create(**{**kwargs, **_defaults}), True
|
||||||
|
|
||||||
async def update_or_create(self, **kwargs: Any) -> "T":
|
async def update_or_create(self, **kwargs: Any) -> "T":
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -102,7 +102,7 @@ def test_payload():
|
|||||||
"native_name": "Thailand",
|
"native_name": "Thailand",
|
||||||
}
|
}
|
||||||
resp = client.post("/", json=payload, headers={"application-type": "json"})
|
resp = client.post("/", json=payload, headers={"application-type": "json"})
|
||||||
print(resp.content)
|
# print(resp.content)
|
||||||
assert resp.status_code == 201
|
assert resp.status_code == 201
|
||||||
|
|
||||||
resp_country = Country(**resp.json())
|
resp_country = Country(**resp.json())
|
||||||
|
|||||||
@ -157,15 +157,17 @@ async def test_bulk_operations_and_fields():
|
|||||||
async def test_working_with_aliases_get_or_create():
|
async def test_working_with_aliases_get_or_create():
|
||||||
async with database:
|
async with database:
|
||||||
async with database.transaction(force_rollback=True):
|
async with database.transaction(force_rollback=True):
|
||||||
artist = await Artist.objects.get_or_create(
|
artist, created = await Artist.objects.get_or_create(
|
||||||
first_name="Teddy", last_name="Bear", born_year=2020
|
first_name="Teddy", last_name="Bear", born_year=2020
|
||||||
)
|
)
|
||||||
assert artist.pk is not None
|
assert artist.pk is not None
|
||||||
|
assert created is True
|
||||||
|
|
||||||
artist2 = await Artist.objects.get_or_create(
|
artist2, created = await Artist.objects.get_or_create(
|
||||||
first_name="Teddy", last_name="Bear", born_year=2020
|
first_name="Teddy", last_name="Bear", born_year=2020
|
||||||
)
|
)
|
||||||
assert artist == artist2
|
assert artist == artist2
|
||||||
|
assert created is False
|
||||||
|
|
||||||
art3 = artist2.dict()
|
art3 = artist2.dict()
|
||||||
art3["born_year"] = 2019
|
art3["born_year"] = 2019
|
||||||
|
|||||||
@ -195,12 +195,18 @@ async def test_queryset_methods():
|
|||||||
comps = await Company.objects.all()
|
comps = await Company.objects.all()
|
||||||
assert [comp.saved for comp in comps]
|
assert [comp.saved for comp in comps]
|
||||||
|
|
||||||
comp2 = await Company.objects.get_or_create(name="Banzai_new", founded=2001)
|
comp2, created = await Company.objects.get_or_create(
|
||||||
|
name="Banzai_new", founded=2001
|
||||||
|
)
|
||||||
assert comp2.saved
|
assert comp2.saved
|
||||||
|
assert created is True
|
||||||
|
|
||||||
comp3 = await Company.objects.get_or_create(name="Banzai", founded=1988)
|
comp3, created = await Company.objects.get_or_create(
|
||||||
|
name="Banzai", founded=1988
|
||||||
|
)
|
||||||
assert comp3.saved
|
assert comp3.saved
|
||||||
assert comp3.pk == comp.pk
|
assert comp3.pk == comp.pk
|
||||||
|
assert created is False
|
||||||
|
|
||||||
update_dict = comp.dict()
|
update_dict = comp.dict()
|
||||||
update_dict["founded"] = 2010
|
update_dict["founded"] = 2010
|
||||||
|
|||||||
@ -102,20 +102,25 @@ async def test_queryset_methods():
|
|||||||
await post.categories.add(news)
|
await post.categories.add(news)
|
||||||
await post.categories.add(breaking)
|
await post.categories.add(breaking)
|
||||||
|
|
||||||
category = await post.categories.get_or_create(name="News")
|
category, created = await post.categories.get_or_create(name="News")
|
||||||
assert category == news
|
assert category == news
|
||||||
assert len(post.categories) == 1
|
assert len(post.categories) == 1
|
||||||
|
assert created is False
|
||||||
|
|
||||||
category = await post.categories.get_or_create(name="Breaking News")
|
category, created = await post.categories.get_or_create(
|
||||||
|
name="Breaking News"
|
||||||
|
)
|
||||||
assert category != breaking
|
assert category != breaking
|
||||||
assert category.pk is not None
|
assert category.pk is not None
|
||||||
assert len(post.categories) == 2
|
assert len(post.categories) == 2
|
||||||
|
assert created is True
|
||||||
|
|
||||||
await post.categories.update_or_create(pk=category.pk, name="Urgent News")
|
await post.categories.update_or_create(pk=category.pk, name="Urgent News")
|
||||||
assert len(post.categories) == 2
|
assert len(post.categories) == 2
|
||||||
cat = await post.categories.get_or_create(name="Urgent News")
|
cat, created = await post.categories.get_or_create(name="Urgent News")
|
||||||
assert cat.pk == category.pk
|
assert cat.pk == category.pk
|
||||||
assert len(post.categories) == 1
|
assert len(post.categories) == 1
|
||||||
|
assert created is False
|
||||||
|
|
||||||
await post.categories.remove(cat)
|
await post.categories.remove(cat)
|
||||||
await cat.delete()
|
await cat.delete()
|
||||||
|
|||||||
@ -166,17 +166,18 @@ async def test_delete_and_update():
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_get_or_create():
|
async def test_get_or_create():
|
||||||
async with database:
|
async with database:
|
||||||
tom = await Book.objects.get_or_create(
|
tom, created = await Book.objects.get_or_create(
|
||||||
title="Volume I", author="Anonymous", genre="Fiction"
|
title="Volume I", author="Anonymous", genre="Fiction"
|
||||||
)
|
)
|
||||||
assert await Book.objects.count() == 1
|
assert await Book.objects.count() == 1
|
||||||
|
assert created is True
|
||||||
|
|
||||||
assert (
|
second_tom, created = await Book.objects.get_or_create(
|
||||||
await Book.objects.get_or_create(
|
|
||||||
title="Volume I", author="Anonymous", genre="Fiction"
|
title="Volume I", author="Anonymous", genre="Fiction"
|
||||||
)
|
)
|
||||||
== tom
|
|
||||||
)
|
assert second_tom.pk == tom.pk
|
||||||
|
assert created is False
|
||||||
assert await Book.objects.count() == 1
|
assert await Book.objects.count() == 1
|
||||||
|
|
||||||
assert await Book.objects.create(
|
assert await Book.objects.create(
|
||||||
@ -188,6 +189,42 @@ async def test_get_or_create():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_or_create_with_defaults():
|
||||||
|
async with database:
|
||||||
|
book, created = await Book.objects.get_or_create(
|
||||||
|
title="Nice book", _defaults={"author": "Mojix", "genre": "Historic"}
|
||||||
|
)
|
||||||
|
assert created is True
|
||||||
|
assert book.author == "Mojix"
|
||||||
|
assert book.title == "Nice book"
|
||||||
|
assert book.genre == "Historic"
|
||||||
|
|
||||||
|
book2, created = await Book.objects.get_or_create(
|
||||||
|
author="Mojix", _defaults={"title": "Book2"}
|
||||||
|
)
|
||||||
|
assert created is False
|
||||||
|
assert book2 == book
|
||||||
|
assert book2.title == "Nice book"
|
||||||
|
assert book2.author == "Mojix"
|
||||||
|
assert book2.genre == "Historic"
|
||||||
|
assert await Book.objects.count() == 1
|
||||||
|
|
||||||
|
book, created = await Book.objects.get_or_create(
|
||||||
|
title="doesn't exist",
|
||||||
|
_defaults={"title": "overwritten", "author": "Mojix", "genre": "Historic"},
|
||||||
|
)
|
||||||
|
assert created is True
|
||||||
|
assert book.title == "overwritten"
|
||||||
|
|
||||||
|
book2, created = await Book.objects.get_or_create(
|
||||||
|
title="overwritten", _defaults={"title": "doesn't work"}
|
||||||
|
)
|
||||||
|
assert created is False
|
||||||
|
assert book2.title == "overwritten"
|
||||||
|
assert book2 == book
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_update_or_create():
|
async def test_update_or_create():
|
||||||
async with database:
|
async with database:
|
||||||
|
|||||||
@ -87,22 +87,26 @@ async def test_quering_by_reverse_fk():
|
|||||||
assert await album.tracks.exists()
|
assert await album.tracks.exists()
|
||||||
assert await album.tracks.count() == 3
|
assert await album.tracks.count() == 3
|
||||||
|
|
||||||
track = await album.tracks.get_or_create(
|
track, created = await album.tracks.get_or_create(
|
||||||
title="The Bird", position=1, play_count=30
|
title="The Bird", position=1, play_count=30
|
||||||
)
|
)
|
||||||
assert track == track1
|
assert track == track1
|
||||||
|
assert created is False
|
||||||
assert len(album.tracks) == 1
|
assert len(album.tracks) == 1
|
||||||
|
|
||||||
track = await album.tracks.get_or_create(
|
track, created = await album.tracks.get_or_create(
|
||||||
title="The Bird2", position=4, play_count=5
|
title="The Bird2", _defaults={"position": 4, "play_count": 5}
|
||||||
)
|
)
|
||||||
assert track != track1
|
assert track != track1
|
||||||
|
assert created is True
|
||||||
assert track.pk is not None
|
assert track.pk is not None
|
||||||
|
assert track.position == 4 and track.play_count == 5
|
||||||
assert len(album.tracks) == 2
|
assert len(album.tracks) == 2
|
||||||
|
|
||||||
await album.tracks.update_or_create(pk=track.pk, play_count=50)
|
await album.tracks.update_or_create(pk=track.pk, play_count=50)
|
||||||
assert len(album.tracks) == 2
|
assert len(album.tracks) == 2
|
||||||
track = await album.tracks.get_or_create(title="The Bird2")
|
track, created = await album.tracks.get_or_create(title="The Bird2")
|
||||||
|
assert created is False
|
||||||
assert track.play_count == 50
|
assert track.play_count == 50
|
||||||
assert len(album.tracks) == 1
|
assert len(album.tracks) == 1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user