add docs
This commit is contained in:
@ -368,6 +368,51 @@ You can set this parameter by providing `Meta` class `constraints` argument.
|
|||||||
--8<-- "../docs_src/models/docs006.py"
|
--8<-- "../docs_src/models/docs006.py"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Model sort order
|
||||||
|
|
||||||
|
When querying the database with given model by default the Model is ordered by the `primary_key`
|
||||||
|
column ascending. If you wish to change the default behaviour you can do it by providing `orders_by`
|
||||||
|
parameter to model `Meta` class.
|
||||||
|
|
||||||
|
Sample default ordering:
|
||||||
|
```python
|
||||||
|
database = databases.Database(DATABASE_URL)
|
||||||
|
metadata = sqlalchemy.MetaData()
|
||||||
|
|
||||||
|
|
||||||
|
class BaseMeta(ormar.ModelMeta):
|
||||||
|
metadata = metadata
|
||||||
|
database = database
|
||||||
|
|
||||||
|
# default sort by column id ascending
|
||||||
|
class Author(ormar.Model):
|
||||||
|
class Meta(BaseMeta):
|
||||||
|
tablename = "authors"
|
||||||
|
|
||||||
|
id: int = ormar.Integer(primary_key=True)
|
||||||
|
name: str = ormar.String(max_length=100)
|
||||||
|
```
|
||||||
|
Modified
|
||||||
|
```python
|
||||||
|
|
||||||
|
database = databases.Database(DATABASE_URL)
|
||||||
|
metadata = sqlalchemy.MetaData()
|
||||||
|
|
||||||
|
|
||||||
|
class BaseMeta(ormar.ModelMeta):
|
||||||
|
metadata = metadata
|
||||||
|
database = database
|
||||||
|
|
||||||
|
# now default sort by name descending
|
||||||
|
class Author(ormar.Model):
|
||||||
|
class Meta(BaseMeta):
|
||||||
|
tablename = "authors"
|
||||||
|
orders_by = ["-name"]
|
||||||
|
|
||||||
|
id: int = ormar.Integer(primary_key=True)
|
||||||
|
name: str = ormar.String(max_length=100)
|
||||||
|
```
|
||||||
|
|
||||||
## Model Initialization
|
## Model Initialization
|
||||||
|
|
||||||
There are two ways to create and persist the `Model` instance in the database.
|
There are two ways to create and persist the `Model` instance in the database.
|
||||||
|
|||||||
@ -1,15 +1,23 @@
|
|||||||
# Aggregation functions
|
# Aggregation functions
|
||||||
|
|
||||||
Currently 2 aggregation functions are supported.
|
Currently 6 aggregation functions are supported.
|
||||||
|
|
||||||
|
|
||||||
* `count() -> int`
|
* `count() -> int`
|
||||||
* `exists() -> bool`
|
* `exists() -> bool`
|
||||||
|
* `sum(columns) -> Any`
|
||||||
|
* `avg(columns) -> Any`
|
||||||
|
* `min(columns) -> Any`
|
||||||
|
* `max(columns) -> Any`
|
||||||
|
|
||||||
|
|
||||||
* `QuerysetProxy`
|
* `QuerysetProxy`
|
||||||
* `QuerysetProxy.count()` method
|
* `QuerysetProxy.count()` method
|
||||||
* `QuerysetProxy.exists()` method
|
* `QuerysetProxy.exists()` method
|
||||||
|
* `QuerysetProxy.sum(columns)` method
|
||||||
|
* `QuerysetProxy.avg(columns)` method
|
||||||
|
* `QuerysetProxy.min(column)` method
|
||||||
|
* `QuerysetProxy.max(columns)` method
|
||||||
|
|
||||||
|
|
||||||
## count
|
## count
|
||||||
@ -68,6 +76,209 @@ class Book(ormar.Model):
|
|||||||
has_sample = await Book.objects.filter(title='Sample').exists()
|
has_sample = await Book.objects.filter(title='Sample').exists()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## sum
|
||||||
|
|
||||||
|
`sum(columns) -> Any`
|
||||||
|
|
||||||
|
Returns sum value of columns for rows matching the given criteria (applied with `filter` and `exclude` if set before).
|
||||||
|
|
||||||
|
You can pass one or many column names including related columns.
|
||||||
|
|
||||||
|
As of now each column passed is aggregated separately (so `sum(col1+col2)` is not possible,
|
||||||
|
you can have `sum(col1, col2)` and later add 2 returned sums in python)
|
||||||
|
|
||||||
|
You cannot `sum` non numeric columns.
|
||||||
|
|
||||||
|
If you aggregate on one column, the single value is directly returned as a result
|
||||||
|
If you aggregate on multiple columns a dictionary with column: result pairs is returned
|
||||||
|
|
||||||
|
Given models like follows
|
||||||
|
|
||||||
|
```Python
|
||||||
|
--8<-- "../docs_src/aggregations/docs001.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
A sample usage might look like following
|
||||||
|
|
||||||
|
```python
|
||||||
|
author = await Author(name="Author 1").save()
|
||||||
|
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
|
||||||
|
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
|
||||||
|
await Book(title="Book 3", year=1923, ranking=5, author=author).save()
|
||||||
|
|
||||||
|
assert await Book.objects.sum("year") == 5773
|
||||||
|
result = await Book.objects.sum(["year", "ranking"])
|
||||||
|
assert result == dict(year=5773, ranking=9)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# cannot sum string column
|
||||||
|
await Book.objects.sum("title")
|
||||||
|
except ormar.QueryDefinitionError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
assert await Author.objects.select_related("books").sum("books__year") == 5773
|
||||||
|
result = await Author.objects.select_related("books").sum(
|
||||||
|
["books__year", "books__ranking"]
|
||||||
|
)
|
||||||
|
assert result == dict(books__year=5773, books__ranking=9)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
await Author.objects.select_related("books")
|
||||||
|
.filter(books__year__lt=1925)
|
||||||
|
.sum("books__year")
|
||||||
|
== 3843
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## avg
|
||||||
|
|
||||||
|
`avg(columns) -> Any`
|
||||||
|
|
||||||
|
Returns avg value of columns for rows matching the given criteria (applied with `filter` and `exclude` if set before).
|
||||||
|
|
||||||
|
You can pass one or many column names including related columns.
|
||||||
|
|
||||||
|
As of now each column passed is aggregated separately (so `sum(col1+col2)` is not possible,
|
||||||
|
you can have `sum(col1, col2)` and later add 2 returned sums in python)
|
||||||
|
|
||||||
|
You cannot `avg` non numeric columns.
|
||||||
|
|
||||||
|
If you aggregate on one column, the single value is directly returned as a result
|
||||||
|
If you aggregate on multiple columns a dictionary with column: result pairs is returned
|
||||||
|
|
||||||
|
```Python
|
||||||
|
--8<-- "../docs_src/aggregations/docs001.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
A sample usage might look like following
|
||||||
|
|
||||||
|
```python
|
||||||
|
author = await Author(name="Author 1").save()
|
||||||
|
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
|
||||||
|
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
|
||||||
|
await Book(title="Book 3", year=1923, ranking=5, author=author).save()
|
||||||
|
|
||||||
|
assert round(float(await Book.objects.avg("year")), 2) == 1924.33
|
||||||
|
result = await Book.objects.avg(["year", "ranking"])
|
||||||
|
assert round(float(result.get("year")), 2) == 1924.33
|
||||||
|
assert result.get("ranking") == 3.0
|
||||||
|
|
||||||
|
try:
|
||||||
|
# cannot avg string column
|
||||||
|
await Book.objects.avg("title")
|
||||||
|
except ormar.QueryDefinitionError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
result = await Author.objects.select_related("books").avg("books__year")
|
||||||
|
assert round(float(result), 2) == 1924.33
|
||||||
|
result = await Author.objects.select_related("books").avg(
|
||||||
|
["books__year", "books__ranking"]
|
||||||
|
)
|
||||||
|
assert round(float(result.get("books__year")), 2) == 1924.33
|
||||||
|
assert result.get("books__ranking") == 3.0
|
||||||
|
|
||||||
|
assert (
|
||||||
|
await Author.objects.select_related("books")
|
||||||
|
.filter(books__year__lt=1925)
|
||||||
|
.avg("books__year")
|
||||||
|
== 1921.5
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## min
|
||||||
|
|
||||||
|
`min(columns) -> Any`
|
||||||
|
|
||||||
|
Returns min value of columns for rows matching the given criteria (applied with `filter` and `exclude` if set before).
|
||||||
|
|
||||||
|
You can pass one or many column names including related columns.
|
||||||
|
|
||||||
|
As of now each column passed is aggregated separately (so `sum(col1+col2)` is not possible,
|
||||||
|
you can have `sum(col1, col2)` and later add 2 returned sums in python)
|
||||||
|
|
||||||
|
If you aggregate on one column, the single value is directly returned as a result
|
||||||
|
If you aggregate on multiple columns a dictionary with column: result pairs is returned
|
||||||
|
|
||||||
|
```Python
|
||||||
|
--8<-- "../docs_src/aggregations/docs001.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
A sample usage might look like following
|
||||||
|
|
||||||
|
```python
|
||||||
|
author = await Author(name="Author 1").save()
|
||||||
|
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
|
||||||
|
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
|
||||||
|
await Book(title="Book 3", year=1923, ranking=5, author=author).save()
|
||||||
|
|
||||||
|
assert await Book.objects.min("year") == 1920
|
||||||
|
result = await Book.objects.min(["year", "ranking"])
|
||||||
|
assert result == dict(year=1920, ranking=1)
|
||||||
|
|
||||||
|
assert await Book.objects.min("title") == "Book 1"
|
||||||
|
|
||||||
|
assert await Author.objects.select_related("books").min("books__year") == 1920
|
||||||
|
result = await Author.objects.select_related("books").min(
|
||||||
|
["books__year", "books__ranking"]
|
||||||
|
)
|
||||||
|
assert result == dict(books__year=1920, books__ranking=1)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
await Author.objects.select_related("books")
|
||||||
|
.filter(books__year__gt=1925)
|
||||||
|
.min("books__year")
|
||||||
|
== 1930
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## max
|
||||||
|
|
||||||
|
`max(columns) -> Any`
|
||||||
|
|
||||||
|
Returns max value of columns for rows matching the given criteria (applied with `filter` and `exclude` if set before).
|
||||||
|
|
||||||
|
Returns min value of columns for rows matching the given criteria (applied with `filter` and `exclude` if set before).
|
||||||
|
|
||||||
|
You can pass one or many column names including related columns.
|
||||||
|
|
||||||
|
As of now each column passed is aggregated separately (so `sum(col1+col2)` is not possible,
|
||||||
|
you can have `sum(col1, col2)` and later add 2 returned sums in python)
|
||||||
|
|
||||||
|
If you aggregate on one column, the single value is directly returned as a result
|
||||||
|
If you aggregate on multiple columns a dictionary with column: result pairs is returned
|
||||||
|
|
||||||
|
```Python
|
||||||
|
--8<-- "../docs_src/aggregations/docs001.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
A sample usage might look like following
|
||||||
|
|
||||||
|
```python
|
||||||
|
author = await Author(name="Author 1").save()
|
||||||
|
await Book(title="Book 1", year=1920, ranking=3, author=author).save()
|
||||||
|
await Book(title="Book 2", year=1930, ranking=1, author=author).save()
|
||||||
|
await Book(title="Book 3", year=1923, ranking=5, author=author).save()
|
||||||
|
|
||||||
|
assert await Book.objects.max("year") == 1930
|
||||||
|
result = await Book.objects.max(["year", "ranking"])
|
||||||
|
assert result == dict(year=1930, ranking=5)
|
||||||
|
|
||||||
|
assert await Book.objects.max("title") == "Book 3"
|
||||||
|
|
||||||
|
assert await Author.objects.select_related("books").max("books__year") == 1930
|
||||||
|
result = await Author.objects.select_related("books").max(
|
||||||
|
["books__year", "books__ranking"]
|
||||||
|
)
|
||||||
|
assert result == dict(books__year=1930, books__ranking=5)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
await Author.objects.select_related("books")
|
||||||
|
.filter(books__year__lt=1925)
|
||||||
|
.max("books__year")
|
||||||
|
== 1923
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
## QuerysetProxy methods
|
## QuerysetProxy methods
|
||||||
|
|
||||||
When access directly the related `ManyToMany` field as well as `ReverseForeignKey`
|
When access directly the related `ManyToMany` field as well as `ReverseForeignKey`
|
||||||
@ -89,6 +300,26 @@ objects from other side of the relation.
|
|||||||
Works exactly the same as [exists](./#exists) function above but allows you to select columns from related
|
Works exactly the same as [exists](./#exists) function above but allows you to select columns from related
|
||||||
objects from other side of the relation.
|
objects from other side of the relation.
|
||||||
|
|
||||||
|
### sum
|
||||||
|
|
||||||
|
Works exactly the same as [sum](./#sum) function above but allows you to sum columns from related
|
||||||
|
objects from other side of the relation.
|
||||||
|
|
||||||
|
### avg
|
||||||
|
|
||||||
|
Works exactly the same as [avg](./#avg) function above but allows you to average columns from related
|
||||||
|
objects from other side of the relation.
|
||||||
|
|
||||||
|
### min
|
||||||
|
|
||||||
|
Works exactly the same as [min](./#min) function above but allows you to select minimum of columns from related
|
||||||
|
objects from other side of the relation.
|
||||||
|
|
||||||
|
### max
|
||||||
|
|
||||||
|
Works exactly the same as [max](./#max) function above but allows you to select maximum of columns from related
|
||||||
|
objects from other side of the relation.
|
||||||
|
|
||||||
!!!tip
|
!!!tip
|
||||||
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
To read more about `QuerysetProxy` visit [querysetproxy][querysetproxy] section
|
||||||
|
|
||||||
|
|||||||
@ -289,7 +289,7 @@ books = (
|
|||||||
```
|
```
|
||||||
|
|
||||||
If you want or need to you can nest deeper conditions as deep as you want, in example to
|
If you want or need to you can nest deeper conditions as deep as you want, in example to
|
||||||
acheive a query like this:
|
achieve a query like this:
|
||||||
|
|
||||||
sql:
|
sql:
|
||||||
```
|
```
|
||||||
@ -564,6 +564,38 @@ assert owner.toys[1].name == "Toy 1"
|
|||||||
|
|
||||||
Something like `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`
|
Something like `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`
|
||||||
|
|
||||||
|
### Default sorting in ormar
|
||||||
|
|
||||||
|
Since order of rows in a database is not guaranteed, `ormar` **always** issues an `order by` sql clause to each (part of) query even if you do not provide order yourself.
|
||||||
|
|
||||||
|
When querying the database with given model by default the `Model` is ordered by the `primary_key`
|
||||||
|
column ascending. If you wish to change the default behaviour you can do it by providing `orders_by`
|
||||||
|
parameter to model `Meta` class.
|
||||||
|
|
||||||
|
!!!tip
|
||||||
|
To read more about models sort order visit [models](../models/index.md#model-sort-order) section of documentation
|
||||||
|
|
||||||
|
By default the relations follow the same ordering, but you can modify the order in which related models are loaded during query by providing `orders_by` and `related_orders_by`
|
||||||
|
parameters to relations.
|
||||||
|
|
||||||
|
!!!tip
|
||||||
|
To read more about models sort order visit [relations](../relations/index.md#relationship-default-sort-order) section of documentation
|
||||||
|
|
||||||
|
Order in which order_by clauses are applied is as follows:
|
||||||
|
|
||||||
|
* Explicitly passed `order_by()` calls in query
|
||||||
|
* Relation passed `orders_by` and `related_orders_by` if exists
|
||||||
|
* Model `Meta` class `orders_by`
|
||||||
|
* Model `primary_key` column ascending (fallback, used if none of above provided)
|
||||||
|
|
||||||
|
**Order from only one source is applied to each `Model` (so that you can always overwrite it in a single query).**
|
||||||
|
|
||||||
|
That means that if you provide explicit `order_by` for a model in a query, the `Relation` and `Model` sort orders are skipped.
|
||||||
|
|
||||||
|
If you provide a `Relation` one, the `Model` sort is skipped.
|
||||||
|
|
||||||
|
Finally, if you provide one for `Model` the default one by `primary_key` is skipped.
|
||||||
|
|
||||||
### QuerysetProxy methods
|
### QuerysetProxy methods
|
||||||
|
|
||||||
When access directly the related `ManyToMany` field as well as `ReverseForeignKey`
|
When access directly the related `ManyToMany` field as well as `ReverseForeignKey`
|
||||||
|
|||||||
@ -128,6 +128,58 @@ class Post(ormar.Model):
|
|||||||
|
|
||||||
It allows you to use `await post.categories.all()` but also `await category.posts.all()` to fetch data related only to specific post, category etc.
|
It allows you to use `await post.categories.all()` but also `await category.posts.all()` to fetch data related only to specific post, category etc.
|
||||||
|
|
||||||
|
## Relationship default sort order
|
||||||
|
|
||||||
|
By default relations follow model default sort order so `primary_key` column ascending, or any sort order se in `Meta` class.
|
||||||
|
|
||||||
|
!!!tip
|
||||||
|
To read more about models sort order visit [models](../models/index.md#model-sort-order) section of documentation
|
||||||
|
|
||||||
|
But you can modify the order in which related models are loaded during query by providing `orders_by` and `related_orders_by`
|
||||||
|
parameters to relations.
|
||||||
|
|
||||||
|
In relations you can sort only by directly related model columns or for `ManyToMany`
|
||||||
|
columns also `Through` model columns `{through_field_name}__{column_name}`
|
||||||
|
|
||||||
|
Sample configuration might look like this:
|
||||||
|
|
||||||
|
```python hl_lines="24"
|
||||||
|
database = databases.Database(DATABASE_URL)
|
||||||
|
metadata = sqlalchemy.MetaData()
|
||||||
|
|
||||||
|
|
||||||
|
class BaseMeta(ormar.ModelMeta):
|
||||||
|
metadata = metadata
|
||||||
|
database = database
|
||||||
|
|
||||||
|
|
||||||
|
class Author(ormar.Model):
|
||||||
|
class Meta(BaseMeta):
|
||||||
|
tablename = "authors"
|
||||||
|
|
||||||
|
id: int = ormar.Integer(primary_key=True)
|
||||||
|
name: str = ormar.String(max_length=100)
|
||||||
|
|
||||||
|
|
||||||
|
class Book(ormar.Model):
|
||||||
|
class Meta(BaseMeta):
|
||||||
|
tablename = "books"
|
||||||
|
|
||||||
|
id: int = ormar.Integer(primary_key=True)
|
||||||
|
author: Optional[Author] = ormar.ForeignKey(
|
||||||
|
Author, orders_by=["name"], related_orders_by=["-year"]
|
||||||
|
)
|
||||||
|
title: str = ormar.String(max_length=100)
|
||||||
|
year: int = ormar.Integer(nullable=True)
|
||||||
|
ranking: int = ormar.Integer(nullable=True)
|
||||||
|
```
|
||||||
|
|
||||||
|
Now calls:
|
||||||
|
|
||||||
|
`await Author.objects.select_related("books").get()` - the books will be sorted by the book year descending
|
||||||
|
|
||||||
|
`await Book.objects.select_related("author").all()` - the authors will be sorted by author name ascending
|
||||||
|
|
||||||
## Self-reference and postponed references
|
## Self-reference and postponed references
|
||||||
|
|
||||||
In order to create auto-relation or create two models that reference each other in at least two
|
In order to create auto-relation or create two models that reference each other in at least two
|
||||||
|
|||||||
@ -192,6 +192,47 @@ Send for `Model.update()` method.
|
|||||||
|
|
||||||
`sender` is a `ormar.Model` class and `instance` is the model that was deleted.
|
`sender` is a `ormar.Model` class and `instance` is the model that was deleted.
|
||||||
|
|
||||||
|
### pre_relation_add
|
||||||
|
|
||||||
|
`pre_relation_add(sender: Type["Model"], instance: "Model", child: "Model",
|
||||||
|
relation_name: str, passed_args: Dict)`
|
||||||
|
|
||||||
|
Send for `Model.relation_name.add()` method for `ManyToMany` relations and reverse side of `ForeignKey` relation.
|
||||||
|
|
||||||
|
`sender` - sender class, `instance` - instance to which related model is added, `child` - model being added,
|
||||||
|
`relation_name` - name of the relation to which child is added, for add signals also `passed_kwargs` - dict of kwargs passed to `add()`
|
||||||
|
|
||||||
|
### post_relation_add
|
||||||
|
|
||||||
|
`post_relation_add(sender: Type["Model"], instance: "Model", child: "Model",
|
||||||
|
relation_name: str, passed_args: Dict)`
|
||||||
|
|
||||||
|
Send for `Model.relation_name.add()` method for `ManyToMany` relations and reverse side of `ForeignKey` relation.
|
||||||
|
|
||||||
|
`sender` - sender class, `instance` - instance to which related model is added, `child` - model being added,
|
||||||
|
`relation_name` - name of the relation to which child is added, for add signals also `passed_kwargs` - dict of kwargs passed to `add()`
|
||||||
|
|
||||||
|
### pre_relation_remove
|
||||||
|
|
||||||
|
`pre_relation_remove(sender: Type["Model"], instance: "Model", child: "Model",
|
||||||
|
relation_name: str)`
|
||||||
|
|
||||||
|
Send for `Model.relation_name.remove()` method for `ManyToMany` relations and reverse side of `ForeignKey` relation.
|
||||||
|
|
||||||
|
`sender` - sender class, `instance` - instance to which related model is added, `child` - model being added,
|
||||||
|
`relation_name` - name of the relation to which child is added.
|
||||||
|
|
||||||
|
### post_relation_remove
|
||||||
|
|
||||||
|
`post_relation_remove(sender: Type["Model"], instance: "Model", child: "Model",
|
||||||
|
relation_name: str, passed_args: Dict)`
|
||||||
|
|
||||||
|
Send for `Model.relation_name.remove()` method for `ManyToMany` relations and reverse side of `ForeignKey` relation.
|
||||||
|
|
||||||
|
`sender` - sender class, `instance` - instance to which related model is added, `child` - model being added,
|
||||||
|
`relation_name` - name of the relation to which child is added.
|
||||||
|
|
||||||
|
|
||||||
## Defining your own signals
|
## Defining your own signals
|
||||||
|
|
||||||
Note that you can create your own signals although you will have to send them manually in your code or subclass `ormar.Model`
|
Note that you can create your own signals although you will have to send them manually in your code or subclass `ormar.Model`
|
||||||
|
|||||||
0
docs_src/aggregations/__init__.py
Normal file
0
docs_src/aggregations/__init__.py
Normal file
36
docs_src/aggregations/docs001.py
Normal file
36
docs_src/aggregations/docs001.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import databases
|
||||||
|
import sqlalchemy
|
||||||
|
|
||||||
|
import ormar
|
||||||
|
from tests.settings import DATABASE_URL
|
||||||
|
|
||||||
|
database = databases.Database(DATABASE_URL)
|
||||||
|
metadata = sqlalchemy.MetaData()
|
||||||
|
|
||||||
|
|
||||||
|
class BaseMeta(ormar.ModelMeta):
|
||||||
|
metadata = metadata
|
||||||
|
database = database
|
||||||
|
|
||||||
|
|
||||||
|
class Author(ormar.Model):
|
||||||
|
class Meta(BaseMeta):
|
||||||
|
tablename = "authors"
|
||||||
|
order_by = ["-name"]
|
||||||
|
|
||||||
|
id: int = ormar.Integer(primary_key=True)
|
||||||
|
name: str = ormar.String(max_length=100)
|
||||||
|
|
||||||
|
|
||||||
|
class Book(ormar.Model):
|
||||||
|
class Meta(BaseMeta):
|
||||||
|
tablename = "books"
|
||||||
|
order_by = ["year", "-ranking"]
|
||||||
|
|
||||||
|
id: int = ormar.Integer(primary_key=True)
|
||||||
|
author: Optional[Author] = ormar.ForeignKey(Author)
|
||||||
|
title: str = ormar.String(max_length=100)
|
||||||
|
year: int = ormar.Integer(nullable=True)
|
||||||
|
ranking: int = ormar.Integer(nullable=True)
|
||||||
@ -71,9 +71,16 @@ class Query:
|
|||||||
self.sorted_orders[clause] = clause.get_text_clause()
|
self.sorted_orders[clause] = clause.get_text_clause()
|
||||||
|
|
||||||
if not current_table_sorted:
|
if not current_table_sorted:
|
||||||
for order_by in self.model_cls.Meta.orders_by:
|
self._apply_default_model_sorting()
|
||||||
clause = ormar.OrderAction(order_str=order_by, model_cls=self.model_cls)
|
|
||||||
self.sorted_orders[clause] = clause.get_text_clause()
|
def _apply_default_model_sorting(self) -> None:
|
||||||
|
"""
|
||||||
|
Applies orders_by from model Meta class (if provided), if it was not provided
|
||||||
|
it was filled by metaclass so it's always there and falls back to pk column
|
||||||
|
"""
|
||||||
|
for order_by in self.model_cls.Meta.orders_by:
|
||||||
|
clause = ormar.OrderAction(order_str=order_by, model_cls=self.model_cls)
|
||||||
|
self.sorted_orders[clause] = clause.get_text_clause()
|
||||||
|
|
||||||
def _pagination_query_required(self) -> bool:
|
def _pagination_query_required(self) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user