work on docs in queries
This commit is contained in:
@ -65,7 +65,7 @@ await track.update(name='The Bird Strikes Again')
|
||||
|
||||
`upsert(**kwargs) -> self`
|
||||
|
||||
It's an proxy to either `save()` or `update(**kwargs)` methods described above.
|
||||
It's a proxy to either `save()` or `update(**kwargs)` methods described above.
|
||||
|
||||
If the primary key is set -> the `update` method will be called.
|
||||
|
||||
|
||||
@ -1,11 +1,23 @@
|
||||
# Create / Insert data into database
|
||||
# Insert data into database
|
||||
|
||||
* `create(**kwargs): -> Model`
|
||||
Following methods allow you to insert data into the database.
|
||||
|
||||
* `create(**kwargs) -> Model`
|
||||
* `get_or_create(**kwargs) -> Model`
|
||||
* `update_or_create(**kwargs) -> Model`
|
||||
* `bulk_create(objects: List[Model]) -> None`
|
||||
* `Model.save()` method
|
||||
* `Model.upsert()` method
|
||||
|
||||
|
||||
* `Model`
|
||||
* `Model.save()` method
|
||||
* `Model.upsert()` method
|
||||
* `Model.save_related()` method
|
||||
|
||||
|
||||
* `QuerysetProxy`
|
||||
* `QuerysetProxy.create(**kwargs)` method
|
||||
* `QuerysetProxy.get_or_create(**kwargs)` method
|
||||
* `QuerysetProxy.update_or_create(**kwargs)` method
|
||||
|
||||
## create
|
||||
|
||||
@ -16,6 +28,17 @@ Creates the model instance, saves it in a database and returns the updates model
|
||||
|
||||
The allowed kwargs are `Model` fields names and proper value types.
|
||||
|
||||
```python
|
||||
class Album(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "album"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
```
|
||||
|
||||
```python
|
||||
malibu = await Album.objects.create(name="Malibu")
|
||||
await Track.objects.create(album=malibu, title="The Bird", position=1)
|
||||
@ -28,7 +51,8 @@ malibu = Album(name="Malibu")
|
||||
await malibu.save()
|
||||
```
|
||||
|
||||
!!!tip Check other `Model` methods in [models][models]
|
||||
!!!tip
|
||||
Check other `Model` methods in [models][models]
|
||||
|
||||
## get_or_create
|
||||
|
||||
@ -39,6 +63,17 @@ Combination of create and get methods.
|
||||
Tries to get a row meeting the criteria and if `NoMatch` exception is raised it creates
|
||||
a new one with given kwargs.
|
||||
|
||||
```python
|
||||
class Album(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "album"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
```
|
||||
|
||||
```python
|
||||
album = await Album.objects.get_or_create(name='The Cat')
|
||||
# object is created as it does not exist
|
||||
@ -47,13 +82,15 @@ assert album == album2
|
||||
# return True as the same db row is returned
|
||||
```
|
||||
|
||||
!!!warning Despite being a equivalent row from database the `album` and `album2` in
|
||||
example above are 2 different python objects!
|
||||
Updating one of them will not refresh the second one until you excplicitly load() the
|
||||
fresh data from db.
|
||||
!!!warning
|
||||
Despite being a equivalent row from database the `album` and `album2` in
|
||||
example above are 2 different python objects!
|
||||
Updating one of them will not refresh the second one until you excplicitly load() the
|
||||
fresh data from db.
|
||||
|
||||
!!!note Note that if you want to create a new object you either have to pass pk column
|
||||
value or pk column has to be set as autoincrement
|
||||
!!!note
|
||||
Note that if you want to create a new object you either have to pass pk column
|
||||
value or pk column has to be set as autoincrement
|
||||
|
||||
## update_or_create
|
||||
|
||||
@ -65,8 +102,9 @@ Updates the model, or in case there is no match in database creates a new one.
|
||||
--8<-- "../docs_src/queries/docs003.py"
|
||||
```
|
||||
|
||||
!!!note Note that if you want to create a new object you either have to pass pk column
|
||||
value or pk column has to be set as autoincrement
|
||||
!!!note
|
||||
Note that if you want to create a new object you either have to pass pk column
|
||||
value or pk column has to be set as autoincrement
|
||||
|
||||
## bulk_create
|
||||
|
||||
@ -80,4 +118,68 @@ A valid list of `Model` objects needs to be passed.
|
||||
--8<-- "../docs_src/queries/docs004.py"
|
||||
```
|
||||
|
||||
## Model method
|
||||
## Model methods
|
||||
|
||||
Each model instance have a set of methods to `save`, `update` or `load` itself.
|
||||
|
||||
###save
|
||||
|
||||
You can create new models by using `QuerySet.create()` method or by initializing your model as a normal pydantic model
|
||||
and later calling `save()` method.
|
||||
|
||||
!!!tip
|
||||
Read more about `save()` method in [models-save][models-save]
|
||||
|
||||
###upsert
|
||||
|
||||
It's a proxy to either `save()` or `update(**kwargs)` methods of a Model.
|
||||
If the pk is not set the `save()` method will be called.
|
||||
|
||||
!!!tip
|
||||
Read more about `upsert()` method in [models-upsert][models-upsert]
|
||||
|
||||
###save_related
|
||||
|
||||
Method goes through all relations of the `Model` on which the method is called,
|
||||
and calls `upsert()` method on each model that is **not** saved.
|
||||
|
||||
!!!tip
|
||||
Read more about `save_related()` method in [models-save-related][models-save-related]
|
||||
|
||||
## QuerysetProxy methods
|
||||
|
||||
When access directly the related `ManyToMany` field as well as `ReverseForeignKey` returns the list of related models.
|
||||
|
||||
But at the same time it exposes subset of QuerySet API, so you can filter, create, select related etc related models directly from parent model.
|
||||
|
||||
### create
|
||||
|
||||
Works exactly the same as [create](./#create) function above but allows you to create related objects
|
||||
from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
|
||||
### get_or_create
|
||||
|
||||
Works exactly the same as [get_or_create](./#get_or_create) function above but allows you to query or create related objects
|
||||
from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
|
||||
### update_or_create
|
||||
|
||||
Works exactly the same as [update_or_create](./#update_or_create) function above but allows you to update or create related objects
|
||||
from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
[models]: ../models/methods.md
|
||||
[models-save]: ../models/methods.md#save
|
||||
[models-upsert]: ../models/methods.md#upsert
|
||||
[models-save-related]: ../models/methods.md#save_related
|
||||
[querysetproxy]: ../relations/queryset-proxy.md
|
||||
@ -1,7 +1,17 @@
|
||||
# Delete/ remove data from database
|
||||
# Delete data from database
|
||||
|
||||
Following methods allow you to delete data from the database.
|
||||
|
||||
* `delete(each: bool = False, **kwargs) -> int`
|
||||
* `Model.delete()` method
|
||||
|
||||
|
||||
* `Model`
|
||||
* `Model.delete()` method
|
||||
|
||||
|
||||
* `QuerysetProxy`
|
||||
* `QuerysetProxy.remove()` method
|
||||
* `QuerysetProxy.clear()` method
|
||||
|
||||
## delete
|
||||
|
||||
@ -20,4 +30,122 @@ Return number of rows deleted.
|
||||
--8<-- "../docs_src/queries/docs005.py"
|
||||
```
|
||||
|
||||
## Model method
|
||||
## Model methods
|
||||
|
||||
Each model instance have a set of methods to `save`, `update` or `load` itself.
|
||||
|
||||
### delete
|
||||
|
||||
You can delete model instance by calling `delete()` method on it.
|
||||
|
||||
!!!tip
|
||||
Read more about `delete()` method in [models methods](../models/methods.md#delete)
|
||||
|
||||
## QuerysetProxy methods
|
||||
|
||||
When access directly the related `ManyToMany` field as well as `ReverseForeignKey`
|
||||
returns the list of related models.
|
||||
|
||||
But at the same time it exposes subset of QuerySet API, so you can filter, create,
|
||||
select related etc related models directly from parent model.
|
||||
|
||||
### remove
|
||||
|
||||
Removal of the related model one by one.
|
||||
|
||||
Removes the relation in the database.
|
||||
|
||||
If you specify the keep_reversed flag to `False` `ormar` will also delete the related model from the database.
|
||||
|
||||
```python
|
||||
class Album(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "albums"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
is_best_seller: bool = ormar.Boolean(default=False)
|
||||
|
||||
class Track(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "tracks"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(Album)
|
||||
title: str = ormar.String(max_length=100)
|
||||
position: int = ormar.Integer()
|
||||
play_count: int = ormar.Integer(nullable=True)
|
||||
```
|
||||
|
||||
```python
|
||||
album = await Album(name="Malibu").save()
|
||||
track1 = await Track(
|
||||
album=album, title="The Bird", position=1, play_count=30,
|
||||
).save()
|
||||
# remove through proxy from reverse side of relation
|
||||
await album.tracks.remove(track1, keep_reversed=False)
|
||||
|
||||
# the track was also deleted
|
||||
tracks = await Track.objects.all()
|
||||
assert len(tracks) == 0
|
||||
```
|
||||
|
||||
### clear
|
||||
|
||||
Removal of all related models in one call.
|
||||
|
||||
Removes also the relation in the database.
|
||||
|
||||
If you specify the keep_reversed flag to `False` `ormar` will also delete the related model from the database.
|
||||
|
||||
```python
|
||||
class Album(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "albums"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
is_best_seller: bool = ormar.Boolean(default=False)
|
||||
|
||||
class Track(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "tracks"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(Album)
|
||||
title: str = ormar.String(max_length=100)
|
||||
position: int = ormar.Integer()
|
||||
play_count: int = ormar.Integer(nullable=True)
|
||||
```
|
||||
|
||||
```python
|
||||
album = await Album(name="Malibu").save()
|
||||
track1 = await Track(
|
||||
album=album,
|
||||
title="The Bird",
|
||||
position=1,
|
||||
play_count=30,
|
||||
).save()
|
||||
track2 = await Track(
|
||||
album=album,
|
||||
title="Heart don't stand a chance",
|
||||
position=2,
|
||||
play_count=20,
|
||||
).save()
|
||||
|
||||
# removes the relation only -> clears foreign keys on tracks
|
||||
await album.tracks.clear()
|
||||
|
||||
# removes also the tracks
|
||||
await album.tracks.clear(keep_reversed=False)
|
||||
```
|
||||
|
||||
[querysetproxy]: ../relations/queryset-proxy.md
|
||||
@ -1,8 +1,26 @@
|
||||
# Filtering and sorting data
|
||||
|
||||
* `filter(**kwargs) -> QuerySet`
|
||||
* `exclude(**kwargs) -> QuerySet`
|
||||
* `order_by(columns:Union[List, str]) -> QuerySet`
|
||||
You can use following methods to filter the data (sql where clause).
|
||||
|
||||
* `filter(**kwargs) -> QuerySet`
|
||||
* `exclude(**kwargs) -> QuerySet`
|
||||
* `get(**kwargs) -> Model`
|
||||
* `get_or_create(**kwargs) -> Model`
|
||||
* `all(**kwargs) -> List[Optional[Model]]`
|
||||
|
||||
|
||||
* `QuerysetProxy`
|
||||
* `QuerysetProxy.filter(**kwargs)` method
|
||||
* `QuerysetProxy.exclude(**kwargs)` method
|
||||
* `QuerysetProxy.get(**kwargs)` method
|
||||
* `QuerysetProxy.get_or_create(**kwargs)` method
|
||||
* `QuerysetProxy.all(**kwargs)` method
|
||||
|
||||
And following methods to sort the data (sql order by clause).
|
||||
|
||||
* `order_by(columns:Union[List, str]) -> QuerySet`
|
||||
* `QuerysetProxy`
|
||||
* `QuerysetProxy.order_by(columns:Union[List, str])` method
|
||||
|
||||
## filter
|
||||
|
||||
@ -36,18 +54,20 @@ You can use special filter suffix to change the filter operands:
|
||||
* endswith - like `album__name__endswith='ibu'` (exact end match)
|
||||
* iendswith - like `album__name__iendswith='IBU'` (exact end match case insensitive)
|
||||
|
||||
!!!note All methods that do not return the rows explicitly returns a QueySet instance so
|
||||
you can chain them together
|
||||
!!!note
|
||||
All methods that do not return the rows explicitly returns a QueySet instance so
|
||||
you can chain them together
|
||||
|
||||
So operations like `filter()`, `select_related()`, `limit()` and `offset()` etc. can be chained.
|
||||
|
||||
Something like `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`
|
||||
|
||||
!!!warning Note that you do not have to specify the `%` wildcard in contains and other
|
||||
filters, it's added for you. If you include `%` in your search value it will be escaped
|
||||
and treated as literal percentage sign inside the text.
|
||||
!!!warning
|
||||
Note that you do not have to specify the `%` wildcard in contains and other
|
||||
filters, it's added for you. If you include `%` in your search value it will be escaped
|
||||
and treated as literal percentage sign inside the text.
|
||||
|
||||
### exclude
|
||||
## exclude
|
||||
|
||||
`exclude(**kwargs) -> QuerySet`
|
||||
|
||||
@ -67,7 +87,41 @@ notes = await Track.objects.exclude(position_gt=3).all()
|
||||
# returns all tracks with position < 3
|
||||
```
|
||||
|
||||
### order_by
|
||||
## QuerysetProxy methods
|
||||
|
||||
When access directly the related `ManyToMany` field as well as `ReverseForeignKey`
|
||||
returns the list of related models.
|
||||
|
||||
But at the same time it exposes subset of QuerySet API, so you can filter, create,
|
||||
select related etc related models directly from parent model.
|
||||
|
||||
### get
|
||||
|
||||
Works exactly the same as [get](./#get) function above but allows you to fetch related
|
||||
objects from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
### get_or_create
|
||||
|
||||
Works exactly the same as [get_or_create](./#get_or_create) function above but allows
|
||||
you to query or create related objects from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
### all
|
||||
|
||||
Works exactly the same as [all](./#all) function above but allows you to query related
|
||||
objects from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
|
||||
|
||||
## order_by
|
||||
|
||||
`order_by(columns: Union[List, str]) -> QuerySet`
|
||||
|
||||
@ -78,12 +132,14 @@ You can provide a string with field name or list of strings with different field
|
||||
|
||||
Ordering in sql will be applied in order of names you provide in order_by.
|
||||
|
||||
!!!tip By default if you do not provide ordering `ormar` explicitly orders by all
|
||||
primary keys
|
||||
!!!tip
|
||||
By default if you do not provide ordering `ormar` explicitly orders by all
|
||||
primary keys
|
||||
|
||||
!!!warning If you are sorting by nested models that causes that the result rows are
|
||||
unsorted by the main model
|
||||
`ormar` will combine those children rows into one main model.
|
||||
!!!warning
|
||||
If you are sorting by nested models that causes that the result rows are
|
||||
unsorted by the main model
|
||||
`ormar` will combine those children rows into one main model.
|
||||
|
||||
Sample raw database rows result (sort by child model desc):
|
||||
```
|
||||
@ -103,7 +159,7 @@ unsorted by the main model
|
||||
Given sample Models like following:
|
||||
|
||||
```python
|
||||
--8 < -- "../docs_src/queries/docs007.py"
|
||||
--8 < -- "../../docs_src/queries/docs007.py"
|
||||
```
|
||||
|
||||
To order by main model field just provide a field name
|
||||
@ -142,10 +198,12 @@ assert owner.toys[0].name == "Toy 4"
|
||||
assert owner.toys[1].name == "Toy 1"
|
||||
```
|
||||
|
||||
!!!note All methods that do not return the rows explicitly returns a QueySet instance so
|
||||
you can chain them together
|
||||
!!!note
|
||||
All methods that do not return the rows explicitly returns a QueySet instance so
|
||||
you can chain them together
|
||||
|
||||
So operations like `filter()`, `select_related()`, `limit()` and `offset()` etc. can be chained.
|
||||
|
||||
Something like `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`
|
||||
|
||||
[querysetproxy]: ../relations/queryset-proxy.md
|
||||
@ -8,8 +8,9 @@ and it's options.
|
||||
Most of the methods are also available through many to many relations and on reverse
|
||||
foreign key relations through `QuerysetProxy` interface.
|
||||
|
||||
!!!info To see which one are supported and how to construct relations
|
||||
visit [relations][relations].
|
||||
!!!info
|
||||
To see which relations are supported and how to construct relations
|
||||
visit [relations][relations].
|
||||
|
||||
For simplicity available methods to fetch and save the data into the database are
|
||||
divided into categories according to the function they fulfill.
|
||||
@ -20,7 +21,7 @@ For complicity also Models and relations methods are listed.
|
||||
|
||||
To read more about any specific section or function please refer to the details subpage.
|
||||
|
||||
### Create
|
||||
###[Insert data into database](./create.md)
|
||||
|
||||
* `create(**kwargs) -> Model`
|
||||
* `get_or_create(**kwargs) -> Model`
|
||||
@ -29,17 +30,17 @@ To read more about any specific section or function please refer to the details
|
||||
|
||||
|
||||
* `Model`
|
||||
* `Model.save()` method
|
||||
* `Model.upsert()` method
|
||||
* `Model.save_related()` method
|
||||
|
||||
* `Model.save()` method
|
||||
* `Model.upsert()` method
|
||||
* `Model.save_related()` method
|
||||
|
||||
|
||||
* `QuerysetProxy`
|
||||
* `QuerysetProxy.create(**kwargs)` method
|
||||
* `QuerysetProxy.get_or_create(**kwargs)` method
|
||||
* `QuerysetProxy.update_or_create(**kwargs)` method
|
||||
* `QuerysetProxy.create(**kwargs)` method
|
||||
* `QuerysetProxy.get_or_create(**kwargs)` method
|
||||
* `QuerysetProxy.update_or_create(**kwargs)` method
|
||||
|
||||
### Read
|
||||
### [Read data from database](./read.md)
|
||||
|
||||
* `get(**kwargs) -> Model`
|
||||
* `get_or_create(**kwargs) -> Model`
|
||||
@ -57,7 +58,7 @@ To read more about any specific section or function please refer to the details
|
||||
* `QuerysetProxy.first()` method
|
||||
* `QuerysetProxy.all(**kwargs)` method
|
||||
|
||||
### Update
|
||||
### [Update data in database](./update.md)
|
||||
|
||||
* `update(each: bool = False, **kwargs) -> int`
|
||||
* `update_or_create(**kwargs) -> Model`
|
||||
@ -73,7 +74,7 @@ To read more about any specific section or function please refer to the details
|
||||
* `QuerysetProxy`
|
||||
* `QuerysetProxy.update_or_create(**kwargs)` method
|
||||
|
||||
### Delete
|
||||
### [Delete data from database](./delete.md)
|
||||
|
||||
* `delete(each: bool = False, **kwargs) -> int`
|
||||
|
||||
@ -86,7 +87,7 @@ To read more about any specific section or function please refer to the details
|
||||
* `QuerysetProxy.remove()` method
|
||||
* `QuerysetProxy.clear()` method
|
||||
|
||||
### Joins and subqueries
|
||||
### [Joins and subqueries](./joins-and-subqueries.md)
|
||||
|
||||
* `select_related(related: Union[List, str]) -> QuerySet`
|
||||
* `prefetch_related(related: Union[List, str]) -> QuerySet`
|
||||
@ -100,7 +101,7 @@ To read more about any specific section or function please refer to the details
|
||||
* `QuerysetProxy.select_related(related: Union[List, str])` method
|
||||
* `QuerysetProxy.prefetch_related(related: Union[List, str])` method
|
||||
|
||||
### Filtering and sorting
|
||||
### [Filtering and sorting](./filter-and-sort.md)
|
||||
|
||||
* `filter(**kwargs) -> QuerySet`
|
||||
* `exclude(**kwargs) -> QuerySet`
|
||||
@ -118,7 +119,7 @@ To read more about any specific section or function please refer to the details
|
||||
* `QuerysetProxy.get_or_create(**kwargs)` method
|
||||
* `QuerysetProxy.all(**kwargs)` method
|
||||
|
||||
### Selecting columns
|
||||
### [Selecting columns](./select-columns.md)
|
||||
|
||||
* `fields(columns: Union[List, str, set, dict]) -> QuerySet`
|
||||
* `exclude_fields(columns: Union[List, str, set, dict]) -> QuerySet`
|
||||
@ -128,7 +129,7 @@ To read more about any specific section or function please refer to the details
|
||||
* `QuerysetProxy.fields(columns: Union[List, str, set, dict])` method
|
||||
* `QuerysetProxy.exclude_fields(columns: Union[List, str, set, dict])` method
|
||||
|
||||
### Pagination and rows number
|
||||
### [Pagination and rows number](./pagination-and-rows-number.md)
|
||||
|
||||
* `paginate(page: int) -> QuerySet`
|
||||
* `limit(limit_count: int) -> QuerySet`
|
||||
@ -142,7 +143,7 @@ To read more about any specific section or function please refer to the details
|
||||
* `QuerysetProxy.limit(limit_count: int)` method
|
||||
* `QuerysetProxy.offset(offset: int)` method
|
||||
|
||||
### Aggregated functions
|
||||
### [Aggregated functions](./aggregations.md)
|
||||
|
||||
* `count() -> int`
|
||||
* `exists() -> bool`
|
||||
@ -153,4 +154,4 @@ To read more about any specific section or function please refer to the details
|
||||
* `QuerysetProxy.exists()` method
|
||||
|
||||
|
||||
[relations]: ./relations/index.md
|
||||
[relations]: ../relations/index.md
|
||||
@ -1,6 +1,18 @@
|
||||
# Joins and subqueries
|
||||
|
||||
To join one table to another, so load also related models you can use following methods.
|
||||
|
||||
* `select_related(related: Union[List, str]) -> QuerySet`
|
||||
* `prefetch_related(related: Union[List, str]) -> QuerySet`
|
||||
|
||||
|
||||
* `Model`
|
||||
* `Model.load()` method
|
||||
|
||||
|
||||
* `QuerysetProxy`
|
||||
* `QuerysetProxy.select_related(related: Union[List, str])` method
|
||||
* `QuerysetProxy.prefetch_related(related: Union[List, str])` method
|
||||
|
||||
## select_related
|
||||
|
||||
@ -30,6 +42,30 @@ To chain related `Models` relation use double underscores between names.
|
||||
!!!tip
|
||||
To control order of models (both main or nested) use `order_by()` method.
|
||||
|
||||
```python
|
||||
class Album(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "albums"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
is_best_seller: bool = ormar.Boolean(default=False)
|
||||
|
||||
class Track(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "tracks"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(Album)
|
||||
title: str = ormar.String(max_length=100)
|
||||
position: int = ormar.Integer()
|
||||
play_count: int = ormar.Integer(nullable=True)
|
||||
```
|
||||
|
||||
```python
|
||||
album = await Album.objects.select_related("tracks").all()
|
||||
# will return album will all columns tracks
|
||||
@ -37,6 +73,52 @@ album = await Album.objects.select_related("tracks").all()
|
||||
|
||||
You can provide a string or a list of strings
|
||||
|
||||
```python
|
||||
class SchoolClass(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "schoolclasses"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
department: Optional[Department] = ormar.ForeignKey(Department, nullable=False)
|
||||
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "categories"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Student(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "students"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
schoolclass: Optional[SchoolClass] = ormar.ForeignKey(SchoolClass)
|
||||
category: Optional[Category] = ormar.ForeignKey(Category, nullable=True)
|
||||
|
||||
|
||||
class Teacher(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "teachers"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
schoolclass: Optional[SchoolClass] = ormar.ForeignKey(SchoolClass)
|
||||
category: Optional[Category] = ormar.ForeignKey(Category, nullable=True)
|
||||
```
|
||||
|
||||
```python
|
||||
classes = await SchoolClass.objects.select_related(
|
||||
["teachers__category", "students"]).all()
|
||||
@ -81,12 +163,82 @@ To chain related `Models` relation use double underscores between names.
|
||||
!!!tip
|
||||
To control order of models (both main or nested) use `order_by()` method.
|
||||
|
||||
```python
|
||||
class Album(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "albums"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
is_best_seller: bool = ormar.Boolean(default=False)
|
||||
|
||||
class Track(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "tracks"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(Album)
|
||||
title: str = ormar.String(max_length=100)
|
||||
position: int = ormar.Integer()
|
||||
play_count: int = ormar.Integer(nullable=True)
|
||||
```
|
||||
|
||||
```python
|
||||
album = await Album.objects.prefetch_related("tracks").all()
|
||||
# will return album will all columns tracks
|
||||
```
|
||||
|
||||
You can provide a string or a list of strings
|
||||
You can provide a string, or a list of strings
|
||||
|
||||
```python
|
||||
class SchoolClass(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "schoolclasses"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
department: Optional[Department] = ormar.ForeignKey(Department, nullable=False)
|
||||
|
||||
|
||||
class Category(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "categories"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Student(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "students"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
schoolclass: Optional[SchoolClass] = ormar.ForeignKey(SchoolClass)
|
||||
category: Optional[Category] = ormar.ForeignKey(Category, nullable=True)
|
||||
|
||||
|
||||
class Teacher(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "teachers"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
schoolclass: Optional[SchoolClass] = ormar.ForeignKey(SchoolClass)
|
||||
category: Optional[Category] = ormar.ForeignKey(Category, nullable=True)
|
||||
```
|
||||
|
||||
```python
|
||||
classes = await SchoolClass.objects.prefetch_related(
|
||||
@ -221,3 +373,44 @@ That means that in `prefetch_related` example above if there are 3 distinct mode
|
||||
table B and 2 in table C, there will be only 5 children nested models shared between all
|
||||
model A instances. That also means that if you update any attribute it will be updated
|
||||
on all parents as they share the same child object.
|
||||
|
||||
|
||||
## Model methods
|
||||
|
||||
Each model instance have a set of methods to `save`, `update` or `load` itself.
|
||||
|
||||
### load
|
||||
|
||||
You can load the `ForeignKey` related model by calling `load()` method.
|
||||
|
||||
`load()` can be used to refresh the model from the database (if it was changed by some other process).
|
||||
|
||||
!!!tip
|
||||
Read more about `load()` method in [models methods](../models/methods.md#load)
|
||||
|
||||
## QuerysetProxy methods
|
||||
|
||||
When access directly the related `ManyToMany` field as well as `ReverseForeignKey`
|
||||
returns the list of related models.
|
||||
|
||||
But at the same time it exposes subset of QuerySet API, so you can filter, create,
|
||||
select related etc related models directly from parent model.
|
||||
|
||||
### select_related
|
||||
|
||||
Works exactly the same as [select_related](./#select_related) function above but allows you to fetch related
|
||||
objects from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
### prefetch_related
|
||||
|
||||
Works exactly the same as [prefetch_related](./#prefetch_related) function above but allows you to fetch related
|
||||
objects from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
|
||||
[querysetproxy]: ../relations/queryset-proxy.md
|
||||
@ -1,29 +1,57 @@
|
||||
# Read/ Load data from database
|
||||
# Read data from database
|
||||
|
||||
* `get(**kwargs): -> Model`
|
||||
* `get_or_create(**kwargs) -> Model`
|
||||
* `first(): -> Model`
|
||||
* `all(**kwargs) -> List[Optional[Model]]`
|
||||
* `Model.load() method`
|
||||
Following methods allow you to load data from the database.
|
||||
|
||||
* `get(**kwargs) -> Model`
|
||||
* `get_or_create(**kwargs) -> Model`
|
||||
* `first() -> Model`
|
||||
* `all(**kwargs) -> List[Optional[Model]]`
|
||||
|
||||
|
||||
* `Model`
|
||||
* `Model.load()` method
|
||||
|
||||
|
||||
* `QuerysetProxy`
|
||||
* `QuerysetProxy.get(**kwargs)` method
|
||||
* `QuerysetProxy.get_or_create(**kwargs)` method
|
||||
* `QuerysetProxy.first()` method
|
||||
* `QuerysetProxy.all(**kwargs)` method
|
||||
|
||||
## get
|
||||
|
||||
`get(**kwargs): -> Model`
|
||||
`get(**kwargs) -> Model`
|
||||
|
||||
Get's the first row from the db meeting the criteria set by kwargs.
|
||||
|
||||
If no criteria set it will return the last row in db sorted by pk.
|
||||
If no criteria set it will return the last row in db sorted by pk column.
|
||||
|
||||
Passing a criteria is actually calling filter(**kwargs) method described below.
|
||||
|
||||
```python
|
||||
class Track(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "track"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(Album)
|
||||
name: str = ormar.String(max_length=100)
|
||||
position: int = ormar.Integer()
|
||||
```
|
||||
|
||||
```python
|
||||
track = await Track.objects.get(name='The Bird')
|
||||
# note that above is equivalent to await Track.objects.filter(name='The Bird').get()
|
||||
track2 = track = await Track.objects.get()
|
||||
track == track2 # True since it's the only row in db in our example
|
||||
track == track2
|
||||
# True since it's the only row in db in our example
|
||||
# and get without arguments return first row by pk column desc
|
||||
```
|
||||
|
||||
!!!warning If no row meets the criteria `NoMatch` exception is raised.
|
||||
!!!warning
|
||||
If no row meets the criteria `NoMatch` exception is raised.
|
||||
|
||||
If there are multiple rows meeting the criteria the `MultipleMatches` exception is raised.
|
||||
|
||||
@ -36,6 +64,17 @@ Combination of create and get methods.
|
||||
Tries to get a row meeting the criteria and if `NoMatch` exception is raised it creates
|
||||
a new one with given kwargs.
|
||||
|
||||
```python
|
||||
class Album(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "album"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
```
|
||||
|
||||
```python
|
||||
album = await Album.objects.get_or_create(name='The Cat')
|
||||
# object is created as it does not exist
|
||||
@ -44,20 +83,41 @@ assert album == album2
|
||||
# return True as the same db row is returned
|
||||
```
|
||||
|
||||
!!!warning Despite being a equivalent row from database the `album` and `album2` in
|
||||
example above are 2 different python objects!
|
||||
Updating one of them will not refresh the second one until you excplicitly load() the
|
||||
fresh data from db.
|
||||
!!!warning
|
||||
Despite being an equivalent row from database the `album` and `album2` in
|
||||
example above are 2 different python objects!
|
||||
Updating one of them will not refresh the second one until you excplicitly load() the
|
||||
fresh data from db.
|
||||
|
||||
!!!note Note that if you want to create a new object you either have to pass pk column
|
||||
value or pk column has to be set as autoincrement
|
||||
!!!note
|
||||
Note that if you want to create a new object you either have to pass pk column
|
||||
value or pk column has to be set as autoincrement
|
||||
|
||||
## first
|
||||
|
||||
`first(): -> Model`
|
||||
`first() -> Model`
|
||||
|
||||
Gets the first row from the db ordered by primary key column ascending.
|
||||
|
||||
```python
|
||||
class Album(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "album"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
```
|
||||
|
||||
```python
|
||||
await Album.objects.create(name='The Cat')
|
||||
await Album.objects.create(name='The Dog')
|
||||
album = await Album.objects.first()
|
||||
# first row by primary_key column asc
|
||||
assert album.name == 'The Cat'
|
||||
```
|
||||
|
||||
## all
|
||||
|
||||
`all(**kwargs) -> List[Optional["Model"]]`
|
||||
@ -69,12 +129,90 @@ Passing kwargs is a shortcut and equals to calling `filter(**kwrags).all()`.
|
||||
If there are no rows meeting the criteria an empty list is returned.
|
||||
|
||||
```python
|
||||
tracks = await Track.objects.select_related("album").all(title='Sample')
|
||||
# will return a list of all Tracks with title Sample
|
||||
class Album(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "album"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
|
||||
|
||||
class Track(ormar.Model):
|
||||
class Meta:
|
||||
tablename = "track"
|
||||
metadata = metadata
|
||||
database = database
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
album: Optional[Album] = ormar.ForeignKey(Album)
|
||||
title: str = ormar.String(max_length=100)
|
||||
position: int = ormar.Integer()
|
||||
```
|
||||
|
||||
```python
|
||||
tracks = await Track.objects.select_related("album").all(album__title='Sample')
|
||||
# will return a list of all Tracks for album Sample
|
||||
# for more on joins visit joining and subqueries section
|
||||
|
||||
tracks = await Track.objects.all()
|
||||
# will return a list of all Tracks in database
|
||||
|
||||
```
|
||||
|
||||
## Model method
|
||||
## Model methods
|
||||
|
||||
Each model instance have a set of methods to `save`, `update` or `load` itself.
|
||||
|
||||
### load
|
||||
|
||||
You can load the `ForeignKey` related model by calling `load()` method.
|
||||
|
||||
`load()` can be used to refresh the model from the database (if it was changed by some other process).
|
||||
|
||||
!!!tip
|
||||
Read more about `load()` method in [models methods](../models/methods.md#load)
|
||||
|
||||
## QuerysetProxy methods
|
||||
|
||||
When access directly the related `ManyToMany` field as well as `ReverseForeignKey`
|
||||
returns the list of related models.
|
||||
|
||||
But at the same time it exposes subset of QuerySet API, so you can filter, create,
|
||||
select related etc related models directly from parent model.
|
||||
|
||||
### get
|
||||
|
||||
Works exactly the same as [get](./#get) function above but allows you to fetch related
|
||||
objects from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
### get_or_create
|
||||
|
||||
Works exactly the same as [get_or_create](./#get_or_create) function above but allows
|
||||
you to query or create related objects from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
### first
|
||||
|
||||
Works exactly the same as [first](./#first) function above but allows you to query
|
||||
related objects from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
### all
|
||||
|
||||
Works exactly the same as [all](./#all) function above but allows you to query related
|
||||
objects from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
|
||||
[querysetproxy]: ../relations/queryset-proxy.md
|
||||
@ -1,11 +1,20 @@
|
||||
# Update
|
||||
# Update data in database
|
||||
|
||||
* `update(each: bool = False, **kwargs) -> int`
|
||||
* `update_or_create(**kwargs) -> Model`
|
||||
* `bulk_update(objects: List[Model], columns: List[str] = None) -> None`
|
||||
* `Model.update() method`
|
||||
* `Model.upsert() method`
|
||||
* `Model.save_related() method`
|
||||
Following methods and functions allow updating existing data in the database.
|
||||
|
||||
* `update(each: bool = False, **kwargs) -> int`
|
||||
* `update_or_create(**kwargs) -> Model`
|
||||
* `bulk_update(objects: List[Model], columns: List[str] = None) -> None`
|
||||
|
||||
|
||||
* `Model`
|
||||
* `Model.update()` method
|
||||
* `Model.upsert()` method
|
||||
* `Model.save_related()` method
|
||||
|
||||
|
||||
* `QuerysetProxy`
|
||||
* `QuerysetProxy.update_or_create(**kwargs)` method
|
||||
|
||||
## update
|
||||
|
||||
@ -24,8 +33,8 @@ Return number of rows updated.
|
||||
--8<-- "../docs_src/queries/docs002.py"
|
||||
```
|
||||
|
||||
!!!warning Queryset needs to be filtered before updating to prevent accidental
|
||||
overwrite.
|
||||
!!!warning
|
||||
Queryset needs to be filtered before updating to prevent accidental overwrite.
|
||||
|
||||
To update whole database table `each=True` needs to be provided as a safety switch
|
||||
|
||||
@ -39,8 +48,9 @@ Updates the model, or in case there is no match in database creates a new one.
|
||||
--8<-- "../docs_src/queries/docs003.py"
|
||||
```
|
||||
|
||||
!!!note Note that if you want to create a new object you either have to pass pk column
|
||||
value or pk column has to be set as autoincrement
|
||||
!!!note
|
||||
Note that if you want to create a new object you either have to pass pk column
|
||||
value or pk column has to be set as autoincrement
|
||||
|
||||
## bulk_update
|
||||
|
||||
@ -67,5 +77,50 @@ completed = await ToDo.objects.filter(completed=False).all()
|
||||
assert len(completed) == 3
|
||||
```
|
||||
|
||||
## Model method
|
||||
## Model methods
|
||||
|
||||
Each model instance have a set of methods to `save`, `update` or `load` itself.
|
||||
|
||||
###update
|
||||
|
||||
You can update models by updating your model attributes (fields) and calling `update()` method.
|
||||
|
||||
If you try to update a model without a primary key set a `ModelPersistenceError` exception will be thrown.
|
||||
|
||||
|
||||
!!!tip
|
||||
Read more about `update()` method in [models-update](../models/methods.md#update)
|
||||
|
||||
###upsert
|
||||
|
||||
It's a proxy to either `save()` or `update(**kwargs)` methods of a Model.
|
||||
If the pk is set the `update()` method will be called.
|
||||
|
||||
!!!tip
|
||||
Read more about `upsert()` method in [models-upsert][models-upsert]
|
||||
|
||||
###save_related
|
||||
|
||||
Method goes through all relations of the `Model` on which the method is called,
|
||||
and calls `upsert()` method on each model that is **not** saved.
|
||||
|
||||
!!!tip
|
||||
Read more about `save_related()` method in [models-save-related][models-save-related]
|
||||
|
||||
## QuerysetProxy methods
|
||||
|
||||
When access directly the related `ManyToMany` field as well as `ReverseForeignKey` returns the list of related models.
|
||||
|
||||
But at the same time it exposes subset of QuerySet API, so you can filter, create, select related etc related models directly from parent model.
|
||||
|
||||
### update_or_create
|
||||
|
||||
Works exactly the same as [update_or_create](./#update_or_create) function above but allows you to update or create related objects
|
||||
from other side of the relation.
|
||||
|
||||
!!!tip
|
||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||
|
||||
[querysetproxy]: ../relations/queryset-proxy.md
|
||||
[models-upsert]: ../models/methods.md#upsert
|
||||
[models-save-related]: ../models/methods.md#save_related
|
||||
@ -84,9 +84,9 @@ nav:
|
||||
- Exceptions: api/exceptions.md
|
||||
repo_name: collerek/ormar
|
||||
repo_url: https://github.com/collerek/ormar
|
||||
google_analytics:
|
||||
- UA-72514911-3
|
||||
- auto
|
||||
#google_analytics:
|
||||
# - UA-72514911-3
|
||||
# - auto
|
||||
theme:
|
||||
name: material
|
||||
highlightjs: true
|
||||
|
||||
Reference in New Issue
Block a user