Перейти к содержанию

Фильтрация и сортировка данных

Вы можете использовать следующие способы фильтрации данных (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 sql).

  • 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):
    ormar_config = base_ormar_config ()

    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):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    Альбом: Optional (Album)= ormar.ForeignKey(альбом)
    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'.

Некоторые образцы:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 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'))
Карьера, рефрит (
    Ом-р (
        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) Можно написать не ноль. 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')

Некоторые образцы:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# sql: (product.name = 'Test' AND product.rating>= 3.0 )
Карьера, рефрит (
    (Product.name == 'Test')& (Product.rating>= 3.0)
get()

# sql: (product.name = 'Test' AND product.rating>= 3.0 )
#       OR (categories.name IN ('Toys', 'Books'))
Карьера, рефрит (
        ((Product.name == 'Test')& (Product.rating>= 3.0))|
        (Product.categories.name <['Toys', 'Books'])
    get()

!!!Обратите внимание, что все методы, которые не возвращают строки, явно возвращают экземпляр QuerySet, чтобы можно было связать их друг с другом

1
2
3
Операторы как такие `filter()`, `select_related()`, `limit()` И `offset()` etc. может быть 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'), то он будет равен «where name = 'John'» в SQL, а 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):
    ormar_config = base_ormar_config ()

    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):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    Альбом: Optional (Album)= ormar.ForeignKey(альбом)
    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 предоставляет две функции, которые можно использовать в filter() и except() в QuerySet и QuerysetProxy.

!!!Примечание Обратите внимание, что вы можете предоставить эти методы в любом другом методе, который принимает*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
«Органа»((
    Database=databases.Database(DATABASE),
    metadata= sqalchemy (),
)


Класс автора (ormar.Model):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    name: str = ormar.String(max_length =100)


Модель (Ormar):
    ormar_config = base_ormar_config ()

    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)

Давайте создадим несколько примеров данных:

1
2
3
4
5
6
7
tolkien = await Author(name="J. R. R. Tolkien").save()
Книга (author=tolkien, title="The Hobbit", 1933).save(
Книга (author=tolkien, title="The Lord of the Rings", год =1955).save(
Книга (author=tolkien, title="The Silmarillion", год =1977).save()
sapkowski = await Author(name="Andrzej Sapkowski").save()
Книга (author=sapkowski, title="The Witcher", год =1990).save()
Книга (author=Sapkowski, title="The Tower of Fools", год =2002).save(

Мы можем создать несколько примеров сложных запросов:

Давайте выберем книги Толкина или книги, написанные после 1970 года.

SQL: WHERE ( authors.name = 'J.R.R. Tolkien' OR books.year > 1970 )

Стиль Джанго

1
2
3
4
5
6
books = (
    Book.objects.select ("author")
    filter(ormar. or_(author__name ="J. R. R. Tolkien", year_gt =1970))
    .all()
)
Assert len(books) = 5

Стиль Python

1
2
3
4
5
6
books = (
    Book.objects.select ("author")
    .filter((Book.author.name=="J. R. R. Tolkien")|(Книга года 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 = (
    Book.objects.select ("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 = (
    Book.objects.select ("author")
    Фильтр (
        Аквал (
            ormar.or_(year__gt =1960, year__lt =1940),
            author__name ="J. R. R. Tolkien",
        )
    )
    .all()
)

Assert len(books) = 2
Название: The Hobbit [0]
[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 = (
    Book.objects.select ("author")
    filter(Книга года)(1960)|(Книга, год, 1940))
    filter(Book.author.name = "J. R. R. Tolkien")
    .all()
)
Assert len(books) = 2

# Option 2 - All in one
books = (
    Book.objects.select ("author")
    Фильтр (
        (
            (Книга «Год года», 1960)|(Книга «Год года», 1940)
        ) & (Book.author.name = "J. R. R. Tolkien")
    )
    .all()
)

Assert len(books) = 2
Название: The Hobbit [0]
[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' ) )

Стиль Джанго

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
books = (
    Book.objects.select ("author")
    Фильтр (
        Ом-р (
            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

1
2
3
4
5
6
7
8
9
books = (
    Book.objects.select ("author")
    Фильтр (    
        (Book.year > 1960) & (Book.author.name = "J. R. R. Tolkien"))|
        (Book.year < 2000) & (Book.author.name = "Andrzej Sapkowski"))
    )
    .all()
)
Assert len(books) = 2

Конечно, эти функции могут иметь более двух условий, так что если мы хотим, чтобы книги содержали «хоббит»:

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%' )

Стиль Джанго

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
books = (
    Book.objects.select ("author")
    Фильтр (
        Ом-р (
            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

1
2
3
4
5
6
7
8
9
books = (
    Book.objects.select ("author")
    Фильтр (    
        (Book.year > 1960) & (Book.author.name = "J. R. R. Tolkien"))|
        (Book.year < 2000) & (Book.author.name = "Andrzej Sapkowski"))|
        (Book.title.icontains("hobbit"))
    )
    .all()
)

Если вы хотите или хотите, вы можете вложить более глубокие условия, например, выполнив следующие запросы:

SQL:

1
2
3
WHERE ( (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 = (
    Book.objects.select ("author")
    Фильтр (
        Ом-р (
            Аквал (
                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
Название: The Hobbit [0]
[1].title = "The Silmarillion"
[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 = (
    Book.objects.select ("author")
    Фильтр (        
        (
            (
            (Книга «Год года», 1960)|
            (Книга «Год года», 1940)
            ) &
            (Book.author.name = "J. R. R. Tolkien")
        ) |
        (
            (Книга "Год" 2000) и
            (Book.author.name = "Andrzej Sapkowski")
        )
    )
    .all()
)
Assert len(books) = 3
Название: The Hobbit [0]
[1].title = "The Silmarillion"
[2].title = "The Witcher"

Теперь вы должны знать, как работают ormar.or_и ormar.and_. Конечно, вы можете связать их с любым другим методом набора запросов, поэтому в примере полностью действительный запрос может выглядеть следующим образом:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
books = (
    Book.objects.select ("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
[0].title = "The Witcher"

То же самое относится и к ссылкам и вложенным в стиле Python.

Стиль Джанго

Обратите внимание, что в стиле django вы не можете предоставлять одни и те же параметры ключевых слов несколько раз, поэтому запрос filter(ormar.or_(name='Jack', name='John')) ниже не разрешен. Если вы хотите проверить несколько значений в одном столбце, просто используйте оператор in:filter(name__in=['Jack','John']).

Если в функцию or_или and_передается только один аргумент, то он заключен в скобки и не влияет на фактический запрос, поэтому все три запроса будут одинаковыми:

1
2
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%')) в примере?

Вы не можете этого сделать:

1
2
3
4
5
6
7
8
books = (
    Book.objects.select ("author")
        (((
        author__name__icontains ="tolkien",
        author__name__icontains ="sapkowski" # you can not use same keyword twice in or_!
    ))                                      # python syntax error
        .all()
)

Но вы можете сделать это:

1
2
3
4
5
6
7
8
9
books = (
    Book.objects.select ("author")
        (((
        ormar. and_(author_name__icontains ="tolkien"), # one argument == just wrapped in ()
        ormar. and_(author__name__icontains ="sapkowski")
    ))
        .all()
)
Assert len(books) = 5

Стиль Python

Обратите внимание, что в стиле Python вы можете использовать одно и то же поле столько раз, сколько захотите.

1
2
3
4
5
6
7
8
books = (
    Book.objects.select ("author")
        Фильтр (
        (Book. author.name.icontains ("tolkien")|
        (Книга author.name.icontains("sapkowski")
    ))                                      
        .all()
)

Получить

get(*args, **kwargs) -> модель

Получите первую строку из базы данных, удовлетворяющую критериям настройки kwargs.

При передаче любых args и/или kwargs это ярлык для вызова filter(*args, **kwargs).get().

!!!tip Для получения дополнительной информации о фильтрах перейдите в раздел Фильтры.

1
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 Для получения дополнительной информации о фильтрах перейдите в раздел Фильтры.

1
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 Для получения дополнительной информации о фильтрах перейдите в раздел Фильтры.

1
To read more about `all` go to [read/all](../read/#all)

Метод QuerysetProxy

При прямом доступе к соответствующему полю ManyToMany и ReverseForeignKey, возвращайтесь к списку связанных моделей.

Но в то же время он предоставляет подмножество API QuerySet, поэтому вы можете фильтровать, создавать и выбирать связанные модели непосредственно из родительской модели.

Фильтр

То же самое, что и предыдущая функция фильтрации, но позволяет фильтровать связанные объекты с другого конца отношения.

Tip

Исключить

То же самое, что и процедура исключения, описанная выше, но позволяет фильтровать связанные объекты с другой стороны отношения.

Tip

Получить

То же самое, что и функция get выше, но позволяет фильтровать связанные объекты с другого конца отношения.

Tip

Получить или нет

То же самое, что и описанное выше get, но если запись базы данных не найдена, то возвращает None, а не вызывает исключения.

Получить или создать

То же самое, что и функция get_or_create выше, но позволяет фильтровать связанные объекты с другого конца отношения.

Tip

Все.

То же самое, что и все вышеперечисленные функции, но позволяет фильтровать связанные объекты с другой стороны отношения.

Tip

Сортировка

Основания для заказа

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
```

Результаты в 2 планах:
```
MODEL: 1 - Child Models: [3, 1] # encountered first in result, all children rows combined
MODEL: 2 - Child Models: [2]
```

Главная модель будет никогда не использоваться в результатах

Ниже приводится пример модели:

 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())

Для сортировки полей главной модели просто укажите имя поля

Стиль Джанго

1
2
3
4
5
6
toys = await Toy.objects.select ("owner"). order_by ("name").all()
assert [x.name.replace("Toys", "") for x in toys] =[
    str(x + 1) для x in range(6)
]
Oner == zeus [0]
[1].owner == aphrodite

Стиль Python

1
2
3
4
5
6
toys = await Toy.objects.select ("owner"). order_by (Toy.name.asc ()).all()
assert [x.name.replace("Toys", "") for x in toys] =[
    str(x + 1) for x in range(6)
]
Oner == zeus [0]
[1].owner == aphrodite

Для сортировки вложенных моделей используйте команду dunder '__' для разделения имен полей.

Таким образом, вы можете сортировать все типы отношений->ForeignKey, обратный виртуальный FK и поля ManyToMany.

Стиль Джанго

1
2
3
4
toys = await Toy.objects.select ("owner"). order_by ("owner").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

1
2
3
4
toys = await Toy.objects.select ("owner"). order_by (Toy.owname.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"

Для сортировки по убыванию перед именем поля следует указать дефис.

Стиль Джанго

1
2
3
4
5
6
7
8
owner (
    Owner.objects.select ("toys").
        . order_by ("-toys__name")
        filter(name=«Zeus»)
        .get()
)
assert owner.toys[0].name = "Toys 4"
assert owner.toys[1].name = "Toys 1"

Стиль Python

1
2
3
4
5
6
7
8
owner (
    Owner.objects.select ("toys")
        . order_by (Owner.toys.name).
        filter(Owner.name == "Zeus")
        .get()
)
assert owner.toys[0].name = "Toys 4"
assert owner.toys[1].name = "Toys 1"

!!!Обратите внимание, что все методы, которые не возвращают строки, явно возвращают экземпляр QuerySet, чтобы можно было связать их друг с другом

1
2
3
So operations like `filter()`,`select_related()`,`limit()` и `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 в порядке возрастания. Если вы хотите изменить поведение по умолчанию, это можно сделать, предоставив параметр orders_by в ormar_config.

!!! Советы для получения дополнительной информации о порядке сортировки моделей см. в разделе "Модель" документа

По умолчанию отношения следуют одному и тому же порядку, но можно изменить порядок загрузки связанных моделей во время запроса, предоставив им параметры orders_by и related_orders_by.

!!! Советы для получения дополнительной информации о порядке сортировки моделей см. в разделе "Взаимоотношения" документа

Предложение order_by применяется в следующем порядке:

  • Выдача вызова order_by () в запросе явно
  • Связь с orders_by и related_orders_by (при наличии)
  • Модель ormar_config объект orders_by
  • Столбец primary_key модели по возрастанию (резервный, используется, если ни один из вышеприведенных)

Применяет заказ только из одного источника к каждой модели (так что вы всегда можете перезаписать его в одном запросе).

Это означает, что, если в запросе модели указано явно order_by, отношения и порядок сортировки модели пропускаются.

Если задать связь 1, сортировка модели будет пропущена.

Наконец, если вы предоставляете модель, то значение по умолчанию primary_key будет пропущено.

Метод QuerysetProxy

При прямом доступе к соответствующему полю ManyToMany и ReverseForeignKey, возвращайтесь к списку связанных моделей.

Но в то же время он предоставляет подмножество API QuerySet, поэтому вы можете фильтровать, создавать и выбирать связанные модели непосредственно из родительской модели.

Основания для заказа

То же самое, что и функция order_by выше, но позволяет сортировать связанные объекты с другой стороны отношения.

Tip