过滤和排序数据
您可以使用以下方法来过滤数据(sql where 子句)。
-
filter(*args, **kwargs) -> QuerySet
-
exclude(*args, **kwargs) -> QuerySet
-
get(*args, **kwargs) -> 模型
-
get_or_none(*args, **kwargs) -> Optional[Model]
-
get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs) -> Tuple[Model, bool]
-
all(*args, **kwargs) -> List[Optional[Model]]
-
查询集代理
QuerysetProxy.filter(*args, **kwargs)
方法
QuerysetProxy.exclude(*args, **kwargs)
方法
QuerysetProxy.get(*args, **kwargs)
方法
QuerysetProxy.get_or_none(*args, **kwargs)
方法
QuerysetProxy.get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs)
方法
QuerysetProxy.all(*args, **kwargs)
方法
并使用以下方法对数据进行排序(sql order by 子句)。
order_by(columns:Union[List, str, OrderAction]) -> QuerySet
- 查询集代理
QuerysetProxy.order_by(columns:Union[List, str, OrderAction])
方法
过滤
筛选
filter(*args, **kwargs) -> QuerySet
允许您使用跨 FK 关系的过滤器按任何模型属性/字段进行过滤以及获取实例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | class Album(ormar.Model):
ormar_config = base_ormar_config.copy()
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):
ormar_config = base_ormar_config.copy()
id: int = ormar.Integer(primary_key=True)
album: Optional[Album] = ormar.ForeignKey(Album)
name: str = ormar.String(max_length=100)
position: int = ormar.Integer()
play_count: int = ormar.Integer(nullable=True)
track = Track.objects.filter(name="The Bird").get()
# will return a track with name equal to 'The Bird'
tracks = Track.objects.filter(album__name="Fantasies").all()
# will return all tracks where the columns album name = 'Fantasies'
|
Django 风格的过滤器
您可以使用特殊的过滤器后缀来更改过滤器操作数:
- 精确 - 与值精确匹配,sql 列 = * 可以写为album__name__exact='Malibu'
- iexact - 精确匹配 sql 列 = (不区分大小写)
- 可以写为album__name__iexact='malibu'
- 包含 - sql 列 LIKE '%%' * 可以写为album__name__contains='Mal'
- icontains - sql 列 LIKE '%%' (不区分大小写)* 可以写为album__name__icontains='mal'
- 在-sql中
column IN (<VALUE1>, <VALUE2>, ...)
* 可以写成 album__name__in=['Malibu', 'Barclay']
- isnull - sql 列 IS NULL(并且 sql 列 IS NOT NULL)
- 可以写为album__name__isnull=True (isnotnull album__name__isnull=False)
- gt - sql 列 > (大于)* 可写为position__gt=3
- gte - sql 列 >= (大于或等于)* 可写为position__gte=3
- lt - sql 列 < (低于)* 可写为position__lt=3
- lte - sql 列 <= (低于等于)* 可写为position__lte=3
- startswith - sql 列 LIKE '%' (精确开始匹配) * 可以写为album__name__startswith='Mal'
- istartswith - sql 列 LIKE '%' (不区分大小写)* 可以写为
album__name__istartswith='mal'
- endswith - sql 列 LIKE '%' (精确结束匹配) * 可以写为album__name__endswith='ibu'
- iendswith - sql 列 LIKE '%' (不区分大小写)* 可以写为album__name__iendswith='IBU'
一些样本:
| # sql: ( product.name = 'Test' AND product.rating >= 3.0 )
Product.objects.filter(name='Test', rating__gte=3.0).get()
# sql: ( product.name = 'Test' AND product.rating >= 3.0 )
# OR (categories.name IN ('Toys', 'Books'))
Product.objects.filter(
ormar.or_(
ormar.and_(name='Test', rating__gte=3.0),
categories__name__in=['Toys', 'Books'])
).get()
# note: to read more about and_ and or_ read complex filters section below
|
Python 风格的过滤器
- 精确 - 与值精确匹配,sql 列 =
- 可以写成 Track.album.name == 'Malibu
- iexact - 精确匹配 sql 列 = (不区分大小写)
- 可以写成
Track.album.name.iexact('malibu')
- 包含 - sql 列 LIKE '%%' * 可以写为 Track.album.name % 'Mal') * 可以写为
Track.album.name.contains('Mal')
- icontains - sql 列 LIKE '%%' (不区分大小写)* 可以写为
Track.album.name.icontains('mal')
- 在-sql中
column IN (<VALUE1>, <VALUE2>, ...)
* 可以写成 Track.album.name << ['Malibu', 'Barclay']
* 可以写成 Track.album.name.in_(['Malibu', 'Barclay'])
- isnull - sql 列 IS NULL(并且 sql 列 IS NOT NULL) * 可以写为 Track.album.name >> None * 可以写为 Track.album.name.isnull(True) * 可以写为 not null作为
Track.album.name.isnull(False)
* not null 可以写成 ~(Track.album.name >> None) * not null 可以写成 ~(Track.album.name.isnull(True))
- gt - sql 列 > (大于)* 可写为 Track.album.name > 3
- gte - sql 列 >= (大于或等于)* 可写为 Track.album.name >= 3
- lt - sql 列 < (低于)* 可写为 Track.album.name < 3
- lte - sql 列 <= (低于等于)* 可写为 Track.album.name <= 3
- startswith - sql 列 LIKE '%' (精确开始匹配)* 可以写为
Track.album.name.startswith('Mal')
- istartswith - sql 列 LIKE '%' (不区分大小写)* 可以写为
Track.album.name.istartswith('mal')
- endswith - sql 列 LIKE '%' (精确结束匹配)* 可以写为
Track.album.name.endswith('ibu')
- iendswith - sql 列 LIKE '%' (不区分大小写)* 可以写为
Track.album.name.iendswith('IBU')
一些样本:
| # sql: ( product.name = 'Test' AND product.rating >= 3.0 )
Product.objects.filter(
(Product.name == 'Test') & (Product.rating >= 3.0)
).get()
# sql: ( product.name = 'Test' AND product.rating >= 3.0 )
# OR (categories.name IN ('Toys', 'Books'))
Product.objects.filter(
((Product.name == 'Test') & (Product.rating >= 3.0)) |
(Product.categories.name << ['Toys', 'Books'])
).get()
|
!!!注意所有不返回行的方法显式返回一个 QuerySet 实例,以便您可以将它们链接在一起
| 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()`
|
!!!警告 请注意,您不必在 contains 和其他过滤器中指定 % 通配符,它是为您添加的。如果您在搜索值中包含 %,它将被转义并被视为文本内的文字百分号。
排除
exclude(*args, **kwargs) -> QuerySet
与过滤器的工作原理完全相同,并且所有修饰符(后缀)都相同,但返回 not 条件。
因此,如果您使用 filter(name='John') ,它等于 SQL 中的 where name = 'John' ,则 except(name='John') 等于 where name <> 'John'
请注意,所有条件都是连接的,因此如果您传递多个值,它将成为条件的并集。
排除(name='John',age>=35) 将变为 where not (name='John' and age>=35)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | class Album(ormar.Model):
ormar_config = base_ormar_config.copy()
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):
ormar_config = base_ormar_config.copy()
id: int = ormar.Integer(primary_key=True)
album: Optional[Album] = ormar.ForeignKey(Album)
name: str = ormar.String(max_length=100)
position: int = ormar.Integer()
play_count: int = ormar.Integer(nullable=True)
notes = await Track.objects.exclude(position_gt=3).all()
# returns all tracks with position < 3
|
复杂过滤器(包括 OR)
默认情况下,filter() 和 except() 方法都将提供的过滤器选项与 AND 条件结合起来,以便 filter(name="John", age__gt=30)
翻译成 WHERE name = 'John' AND age > 30
。
有时,使用不应联合应用的条件查询数据库很有用,例如 WHERE name = 'John' OR age > 30
,或者构建一个复杂的 where 查询,您希望对其有更大的控制。毕竟 WHERE (name = 'John' OR age > 30) and city='New York'
完全不同于 WHERE name = 'John' OR (age > 30 and city='New York')
。
为了构建 OR 和嵌套条件,ormar 提供了两个函数,可以在 QuerySet 和 QuerysetProxy 中的 filter() 和 except() 中使用。
!!!note 请注意,您可以在接受 *args 的任何其他方法(例如 get() 或 all())中提供这些方法。
对 or_ 和 and_ 的调用可以相互嵌套,也可以与关键字参数组合。由于听起来比实际更复杂,让我们看一些例子。
给定一个这样的示例模型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | base_ormar_config = ormar.OrmarConfig(
database=databases.Database(DATABASE_URL),
metadata=sqlalchemy.MetaData(),
)
class Author(ormar.Model):
ormar_config = base_ormar_config.copy()
id: int = ormar.Integer(primary_key=True)
name: str = ormar.String(max_length=100)
class Book(ormar.Model):
ormar_config = base_ormar_config.copy()
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)
|
让我们创建一些示例数据:
| tolkien = await Author(name="J.R.R. Tolkien").save()
await Book(author=tolkien, title="The Hobbit", year=1933).save()
await Book(author=tolkien, title="The Lord of the Rings", year=1955).save()
await Book(author=tolkien, title="The Silmarillion", year=1977).save()
sapkowski = await Author(name="Andrzej Sapkowski").save()
await Book(author=sapkowski, title="The Witcher", year=1990).save()
await Book(author=sapkowski, title="The Tower of Fools", year=2002).save()
|
我们可以构建一些示例复杂查询:
让我们选择托尔金的书或 1970 年之后写的书
sql: WHERE ( authors.name = 'J.R.R. Tolkien' OR books.year > 1970 )
姜戈风格
| books = (
await Book.objects.select_related("author")
.filter(ormar.or_(author__name="J.R.R. Tolkien", year__gt=1970))
.all()
)
assert len(books) == 5
|
Python风格
| books = (
await Book.objects.select_related("author")
.filter((Book.author.name=="J.R.R. Tolkien") | (Book.year > 1970))
.all()
)
assert len(books) == 5
|
现在让我们选择 1960 年之后或 1940 年之前由托尔金写的书。
sql: WHERE ( books.year > 1960 OR books.year < 1940 ) AND authors.name = 'J.R.R. Tolkien'
姜戈风格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | # OPTION 1 - split and into separate call
books = (
await Book.objects.select_related("author")
.filter(ormar.or_(year__gt=1960, year__lt=1940))
.filter(author__name="J.R.R. Tolkien")
.all()
)
assert len(books) == 2
# OPTION 2 - all in one
books = (
await Book.objects.select_related("author")
.filter(
ormar.and_(
ormar.or_(year__gt=1960, year__lt=1940),
author__name="J.R.R. Tolkien",
)
)
.all()
)
assert len(books) == 2
assert books[0].title == "The Hobbit"
assert books[1].title == "The Silmarillion"
|
Python风格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | books = (
await Book.objects.select_related("author")
.filter((Book.year > 1960) | (Book.year < 1940))
.filter(Book.author.name == "J.R.R. Tolkien")
.all()
)
assert len(books) == 2
# OPTION 2 - all in one
books = (
await Book.objects.select_related("author")
.filter(
(
(Book.year > 1960) | (Book.year < 1940)
) & (Book.author.name == "J.R.R. Tolkien")
)
.all()
)
assert len(books) == 2
assert books[0].title == "The Hobbit"
assert books[1].title == "The Silmarillion"
|
2000 年之前萨普科夫斯基的书籍或 1960 年之后托尔金的书籍
sql: WHERE ( ( books.year > 1960 AND authors.name = 'J.R.R. Tolkien' ) OR ( books.year < 2000 AND authors.name = 'Andrzej Sapkowski' ) )
姜戈风格
| books = (
await Book.objects.select_related("author")
.filter(
ormar.or_(
ormar.and_(year__gt=1960, author__name="J.R.R. Tolkien"),
ormar.and_(year__lt=2000, author__name="Andrzej Sapkowski"),
)
)
.all()
)
assert len(books) == 2
|
Python风格
| books = (
await Book.objects.select_related("author")
.filter(
((Book.year > 1960) & (Book.author.name == "J.R.R. Tolkien")) |
((Book.year < 2000) & (Book.author.name == "Andrzej Sapkowski"))
)
.all()
)
assert len(books) == 2
|
当然,这些函数可以有两个以上的条件,所以如果我们想要包含“hobbit”的书籍:
sql: WHERE ( ( books.year > 1960 AND authors.name = 'J.R.R. Tolkien' ) OR ( books.year < 2000 AND os0cec_authors.name = 'Andrzej Sapkowski' ) OR books.title LIKE '%hobbit%' )
姜戈风格
| books = (
await Book.objects.select_related("author")
.filter(
ormar.or_(
ormar.and_(year__gt=1960, author__name="J.R.R. Tolkien"),
ormar.and_(year__lt=2000, author__name="Andrzej Sapkowski"),
title__icontains="hobbit",
)
)
.all()
)
|
Python风格
| books = (
await Book.objects.select_related("author")
.filter(
((Book.year > 1960) & (Book.author.name == "J.R.R. Tolkien")) |
((Book.year < 2000) & (Book.author.name == "Andrzej Sapkowski")) |
(Book.title.icontains("hobbit"))
)
.all()
)
|
如果您愿意或需要,您可以根据需要嵌套更深的条件,例如实现如下查询:
sql:
| WHERE ( ( ( books.year > 1960 OR books.year < 1940 )
AND authors.name = 'J.R.R. Tolkien' ) OR
( books.year < 2000 AND authors.name = 'Andrzej Sapkowski' ) )
|
您可以按如下方式构造查询:
姜戈风格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | books = (
await Book.objects.select_related("author")
.filter(
ormar.or_(
ormar.and_(
ormar.or_(year__gt=1960, year__lt=1940),
author__name="J.R.R. Tolkien",
),
ormar.and_(year__lt=2000, author__name="Andrzej Sapkowski"),
)
)
.all()
)
assert len(books) == 3
assert books[0].title == "The Hobbit"
assert books[1].title == "The Silmarillion"
assert books[2].title == "The Witcher"
|
Python风格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | books = (
await Book.objects.select_related("author")
.filter(
(
(
(Book.year > 1960) |
(Book.year < 1940)
) &
(Book.author.name == "J.R.R. Tolkien")
) |
(
(Book.year < 2000) &
(Book.author.name == "Andrzej Sapkowski")
)
)
.all()
)
assert len(books) == 3
assert books[0].title == "The Hobbit"
assert books[1].title == "The Silmarillion"
assert books[2].title == "The Witcher"
|
现在您应该已经了解 ormar.or_ 和 ormar.and_ 的工作原理。当然,您可以将它们链接到查询集的任何其他方法中,因此在示例中,一个完全有效的查询可能如下所示:
| books = (
await Book.objects.select_related("author")
.filter(ormar.or_(year__gt=1980, author__name="Andrzej Sapkowski"))
.filter(title__startswith="The")
.limit(1)
.offset(1)
.order_by("-id")
.all()
)
assert len(books) == 1
assert books[0].title == "The Witcher"
|
这同样适用于 python 风格的链接和嵌套。
姜戈风格
请注意,使用 django 风格,您不能多次提供相同的关键字参数,因此查询如下 filter(ormar.or_(name='Jack', name='John'))
是不允许的。如果您想检查同一列的多个值,只需使用 in 运算符: filter(name__in=['Jack','John'])
。
如果只向 or_ 或 and_ 函数传递一个参数,则它只是用括号括起来,对实际查询没有影响,因此最终所有 3 个查询都是相同的:
| await Book.objects.filter(title='The Hobbit').get()
await Book.objects.filter(ormar.or_(title='The Hobbit')).get()
await Book.objects.filter(ormar.and_(title='The Hobbit')).get()
|
!!!note 注意 or_ 和 and_ 查询会有 WHERE (title='The Hobbit') 但括号是多余的并且没有实际效果。
如果您确实需要使用相同的字段名称两次,则可以使用此功能。请记住,您不能将相同的关键字参数两次传递给函数,因此如何在示例中查询 WHERE (authors.name LIKE '%tolkien%') OR (authors.name LIKE '%sapkowski%'))
?
你不能这样做:
| books = (
await Book.objects.select_related("author")
.filter(ormar.or_(
author__name__icontains="tolkien",
author__name__icontains="sapkowski" # you cannot use same keyword twice in or_!
)) # python syntax error
.all()
)
|
但你可以这样做:
| books = (
await Book.objects.select_related("author")
.filter(ormar.or_(
ormar.and_(author__name__icontains="tolkien"), # one argument == just wrapped in ()
ormar.and_(author__name__icontains="sapkowski")
))
.all()
)
assert len(books) == 5
|
Python风格
请注意,使用 python 风格,您可以根据需要多次使用相同的字段。
| books = (
await Book.objects.select_related("author")
.filter(
(Book.author.name.icontains("tolkien")) |
(Book.author.name.icontains("sapkowski"))
))
.all()
)
|
得到
get(*args, **kwargs) -> 模型
从数据库中获取满足 kwargs 设置条件的第一行。
当传递任何 args 和/或 kwargs 时,它是相当于调用 filter(*args, **kwargs).get() 的快捷方式
!!!tip 要了解有关过滤器的更多信息,请转到过滤器。
| To read more about `get` go to [read/get](../read/#get)
|
获取或无
与上面描述的 get 完全相同,但如果没有找到与条件匹配的数据库记录,则返回 None,而不是引发异常。
获取或创建
get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs) -> Tuple[Model, bool]
创建和获取方法的组合。
当传递任何 args 和/或 kwargs 时,它是相当于调用的快捷方式 filter(*args, **kwargs).get_or_create()
!!!tip 要了解有关过滤器的更多信息,请转到过滤器。
| To read more about `get_or_create` go to [read/get_or_create](../read/#get_or_create)
|
!!!警告当给定的项目不存在时,您需要为模型的所有必填字段传递 kwargs,包括但不限于 Primary_key 列(除非它是自动增量)。
全部
all(*args, **kwargs) -> List[Optional["Model"]]
对于设置的过滤器选项,返回给定模型的数据库中的所有行。
当传递任何 kwargs 时,它是相当于调用 filter(*args, **kwargs).all() 的快捷方式
!!!tip 要了解有关过滤器的更多信息,请转到过滤器。
| To read more about `all` go to [read/all](../read/#all)
|
QuerysetProxy 方法
当直接访问相关的ManyToMany字段以及ReverseForeignKey时,返回相关模型的列表。
但同时它公开了 QuerySet API 的子集,因此您可以直接从父模型过滤、创建、选择相关模型等。
筛选
与上面的过滤功能完全相同,但允许您从关系的另一端过滤相关对象。
!!!tip 要了解有关 QuerysetProxy 的更多信息,请访问 querysetproxy 部分
排除
与上面的排除功能完全相同,但允许您从关系的另一侧过滤相关对象。
!!!tip 要了解有关 QuerysetProxy 的更多信息,请访问 querysetproxy 部分
得到
与上面的 get 函数完全相同,但允许您从关系的另一端过滤相关对象。
!!!tip 要了解有关 QuerysetProxy 的更多信息,请访问 querysetproxy 部分
获取或无
与上面描述的 get 完全相同,但如果没有找到与条件匹配的数据库记录,则返回 None,而不是引发异常。
获取或创建
与上面的 get_or_create 函数完全相同,但允许您从关系的另一端过滤相关对象。
!!!tip 要了解有关 QuerysetProxy 的更多信息,请访问 querysetproxy 部分
全部
与上面所有功能完全相同,但允许您从关系的另一侧过滤相关对象。
!!!tip 要了解有关 QuerysetProxy 的更多信息,请访问 querysetproxy 部分
排序
订单依据
order_by(columns: Union[List, str, OrderAction]) -> QuerySet
使用 order_by(),您可以根据您选择的字段对数据库中的结果进行排序。
您可以提供带有字段名称的字符串或带有不同字段的字符串列表。
sql 中的排序将按照您在 order_by 中提供的名称的顺序应用。
!!!tip 默认情况下,如果您不提供排序或按所有主键显式排序
!!!警告如果您按嵌套模型排序,会导致结果行未按主模型排序,否则 mar 会将这些子行合并到一个主模型中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | Sample raw database rows result (sort by child model desc):
```
MODEL: 1 - Child Model - 3
MODEL: 2 - Child Model - 2
MODEL: 1 - Child Model - 1
```
will result in 2 rows of result:
```
MODEL: 1 - Child Models: [3, 1] # encountered first in result, all children rows combined
MODEL: 2 - Child Models: [2]
```
The main model will never duplicate in the result
|
给定示例模型如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 | import asyncio
import databases
import ormar
import sqlalchemy
from examples import create_drop_database
DATABASE_URL = "sqlite:///test.db"
ormar_base_config = ormar.OrmarConfig(
database=databases.Database(DATABASE_URL),
metadata=sqlalchemy.MetaData(),
)
class Owner(ormar.Model):
ormar_config = ormar_base_config.copy(tablename="owners")
id: int = ormar.Integer(primary_key=True)
name: str = ormar.String(max_length=100)
class Toy(ormar.Model):
ormar_config = ormar_base_config.copy(tablename="toys")
id: int = ormar.Integer(primary_key=True)
name: str = ormar.String(max_length=100)
owner: Owner = ormar.ForeignKey(Owner)
@create_drop_database(base_config=ormar_base_config)
async def run_query():
# build some sample data
aphrodite = await Owner.objects.create(name="Aphrodite")
hermes = await Owner.objects.create(name="Hermes")
zeus = await Owner.objects.create(name="Zeus")
await Toy.objects.create(name="Toy 4", owner=zeus)
await Toy.objects.create(name="Toy 5", owner=hermes)
await Toy.objects.create(name="Toy 2", owner=aphrodite)
await Toy.objects.create(name="Toy 1", owner=zeus)
await Toy.objects.create(name="Toy 3", owner=aphrodite)
await Toy.objects.create(name="Toy 6", owner=hermes)
asyncio.run(run_query())
|
要按主模型字段排序,只需提供字段名称
姜戈风格
| toys = await Toy.objects.select_related("owner").order_by("name").all()
assert [x.name.replace("Toy ", "") for x in toys] == [
str(x + 1) for x in range(6)
]
assert toys[0].owner == zeus
assert toys[1].owner == aphrodite
|
Python风格
| toys = await Toy.objects.select_related("owner").order_by(Toy.name.asc()).all()
assert [x.name.replace("Toy ", "") for x in toys] == [
str(x + 1) for x in range(6)
]
assert toys[0].owner == zeus
assert toys[1].owner == aphrodite
|
要对嵌套模型进行排序,请使用 dunder '__' 分隔字段名称。
您可以通过这种方式对所有关系类型 ->ForeignKey、反向虚拟 FK 和 ManyToMany 字段进行排序。
姜戈风格
| toys = await Toy.objects.select_related("owner").order_by("owner__name").all()
assert toys[0].owner.name == toys[1].owner.name == "Aphrodite"
assert toys[2].owner.name == toys[3].owner.name == "Hermes"
assert toys[4].owner.name == toys[5].owner.name == "Zeus"
|
Python风格
| toys = await Toy.objects.select_related("owner").order_by(Toy.owner.name.asc()).all()
assert toys[0].owner.name == toys[1].owner.name == "Aphrodite"
assert toys[2].owner.name == toys[3].owner.name == "Hermes"
assert toys[4].owner.name == toys[5].owner.name == "Zeus"
|
要按降序排序,请在字段名称前面提供连字符
姜戈风格
| owner = (
await Owner.objects.select_related("toys")
.order_by("-toys__name")
.filter(name="Zeus")
.get()
)
assert owner.toys[0].name == "Toy 4"
assert owner.toys[1].name == "Toy 1"
|
Python风格
| owner = (
await Owner.objects.select_related("toys")
.order_by(Owner.toys.name.desc())
.filter(Owner.name == "Zeus")
.get()
)
assert owner.toys[0].name == "Toy 4"
assert owner.toys[1].name == "Toy 1"
|
!!!注意所有不返回行的方法显式返回一个 QuerySet 实例,以便您可以将它们链接在一起
| 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()`
|
ormar 中的默认排序
由于无法保证数据库中行的顺序,因此即使您自己不提供顺序,ormar 也始终向每个(部分)查询发出 order by sql 子句。
默认情况下,使用给定模型查询数据库时,模型按 Primary_key 列升序排序。如果您希望更改默认行为,可以通过向 ormar_config 提供orders_by 参数来实现。
!!!提示要了解有关模型排序顺序的更多信息,请访问文档的模型部分
默认情况下,关系遵循相同的顺序,但您可以通过向关系提供orders_by 和 related_orders_by 参数来修改查询期间加载相关模型的顺序。
!!!提示要阅读有关模型排序顺序的更多信息,请访问文档的关系部分
order_by 子句的应用顺序如下:
- 在查询中显式传递 order_by() 调用
- 关系通过orders_by 和 related_orders_by(如果存在)
- 模型的 ormar_config 对象orders_by
- 模型的primary_key列升序(后备,如果以上均未提供则使用)
仅将来自一个来源的订单应用于每个模型(以便您始终可以在单个查询中覆盖它)。
这意味着,如果您在查询中为模型提供显式 order_by,则将跳过关系和模型排序顺序。
如果您提供关系一,则会跳过模型排序。
最后,如果您为 Model 提供一个,则primary_key 的默认值将被跳过。
QuerysetProxy 方法
当直接访问相关的ManyToMany字段以及ReverseForeignKey时,返回相关模型的列表。
但同时它公开了 QuerySet API 的子集,因此您可以直接从父模型过滤、创建、选择相关模型等。
订单依据
与上面的 order_by 函数完全相同,但允许您从关系的另一侧对相关对象进行排序。
!!!tip 要了解有关 QuerysetProxy 的更多信息,请访问 querysetproxy 部分