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

Выбор подгруппы столбцов

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

  • fields(columns: Union[List, str, set, dict]) -> QuerySet

  • exclude_fields(columns: Union[List, str, set, dict]) -> QuerySet

  • Агент набора запросов

    • QuerysetProxy.fields(columns: Union[List, str, set, dict]) Методология
    • QuerysetProxy.exclude_fields(columns: Union[List, str, set, dict]) Методологии

Область применения

fields(columns: Union[List, str, set, dict]) -> QuerySet

С помощью fields() можно выбрать подмножество столбцов модели для ограничения нагрузки на данные.

Обратите внимание на то, что fields() и except_fields () применяются как к главной модели (в обычных запросах, таких как get, all и т. д.), так и к моделям select_lated и prefetch_lated (с использованием вложенных представлений).

Ниже приведены примеры данных:

 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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import asyncio

import databases
import ormar
import sqlalchemy
from examples import create_drop_database
from tests.settings import DATABASE_URL

base_ormar_config = ormar.OrmarConfig(
    database=databases.Database(DATABASE_URL, force_rollback=True),
    metadata=sqlalchemy.MetaData(),
)


class Company(ormar.Model):
    ormar_config = base_ormar_config.copy(tablename="companies")

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


class Car(ormar.Model):
    ormar_config = base_ormar_config.copy()

    id: int = ormar.Integer(primary_key=True)
    manufacturer = ormar.ForeignKey(Company)
    name: str = ormar.String(max_length=100)
    year: int = ormar.Integer(nullable=True)
    gearbox_type: str = ormar.String(max_length=20, nullable=True)
    gears: int = ormar.Integer(nullable=True)
    aircon_type: str = ormar.String(max_length=20, nullable=True)


@create_drop_database(base_config=base_ormar_config)
async def sample_data():
    # build some sample data
    toyota = await Company.objects.create(name="Toyota", founded=1937)
    await Car.objects.create(
        manufacturer=toyota,
        name="Corolla",
        year=2020,
        gearbox_type="Manual",
        gears=5,
        aircon_type="Manual",
    )
    await Car.objects.create(
        manufacturer=toyota,
        name="Yaris",
        year=2019,
        gearbox_type="Manual",
        gears=5,
        aircon_type="Manual",
    )
    await Car.objects.create(
        manufacturer=toyota,
        name="Supreme",
        year=2020,
        gearbox_type="Auto",
        gears=6,
        aircon_type="Auto",
    )


asyncio.run(sample_data())

Вы можете выбрать, что указанное поле str, List[str], Set[str] or dict имеет вложенное определение, передав его.

Для включения связанной модели используйте символ {related_name}__{column}[__{optional_next} etc.].

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Аквал (
    Car.objects
    . select_related ('manufacturer')
    .fields(['id', 'name','manufacturer__name'])
    .all()
)
Для автомобилей в ALL_Cars:
    # excluded columns Will yield None
    assert all(getattr(car, x) is None for x in ['year','gearbox_type','gears','aircon_type'])
    # included column on related models will be available, pk column is always included
    Если вы не включите это в список fields
    assert car.manufacturer.name = 'Toyota'
    #также в неофициально переходящих модулях- you can not exclude pk - it's Always auto added
    Manufacturer.Founded is None

fields() можно вызвать несколько раз для создания столбцов для выбора.

Если в вызов select_lated () включены связанные модели, то в поле для этих моделей не указывается столбец

  • Это список всех полей этих вложенных моделей.

    Аквал ( Car.objects . select_related ('manufacturer') .fields ('id') fields([name ']) .all() )

    All fields from company model Are Selected

    assert all_cars [0]. manufacturer.name = 'Toyota' assert all_cars [0].manufacturer.founded == 1937

!!! warning не может исключать обязательные поля, так как они генерируют ValidationError, поля, необходимые для исключения, должны быть пустыми.

1
2
Метод `values()` может быть использован для извлечения данных из mandatory fields, though data will
Be Returned as a `dict`.

Вы не можете исключить обязательный столбец типа-имя производителя__в данном примере.

1
2
3
4
5
6
7
Авариум (
    Car.objects
    . select_related ('manufacturer')
    .fields(['id', 'name','manufacturer__founded'])
    .all()
)
# will raise pydantic ValidationError as company.name is required

!!!Столбец tip Pk не может быть исключен-он всегда добавляется автоматически, даже если он не включен явно.

Можно также передать поля, которые требуется включить в словарь или набор.

Чтобы пометить поле как включенное в словарь, используйте его имя в качестве ключа, а многоточие-в качестве значения.

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

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

Чтобы включить всю вложенную модель, укажите имя и многоточие полей, относящихся к модели.

Ниже приведен пример эквивалентности:

 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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 1. like in example above
Авариум (
    Car.objects
    . select_related ('manufacturer')
    .fields(['id', 'name','manufacturer__name'])
    .all()
)

To mark a field as required use ellipsis
Авариум (
    Car.objects
    . select_related ('manufacturer')
    .fields({'id': ...,
             'name':...,
             «Manufacturer»:{
                 'Name':...
                }
             })
    .all()
)

# 3. to include whole nested model use ellipsis
Авариум (
    Car.objects
    . select_related ('manufacturer')
    .fields({'id': ...,
             'name':...,
             "Manufacturer":...
             })
    .all()
)

to specify fields at last nesting level
Вы можете также использовать Set - equivalent to 2.above
Авариум (
    Car.objects
    . select_related ('manufacturer')
    .fields({'id': ...,
             'name':...,
             «Manufacturer»: {'name'}
             })
    .all()
)

О чем можно говорить в нескольких стильных стилях.
Авариум (
    Car.objects
    . select_related ('manufacturer')
    .fields({'id': ...,
             'name':...,
             «Manufacturer»: {'name', 'founded'}
             })
    .all()
)

Вы можете include All Nested Fields.
«But It Will Be equivalent of 3. Above Which Is Shorter»
Авариум (
    Car.objects
    . select_related ('manufacturer')
    .fields({'id': ...,
             'name':...,
             «Manufacturer»: {'id', 'name', 'founded'}
             })
    .all()
)

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

1
2
3
So operations like `filter()`,`select_related()`,`limit()` и `offset()` etc.can be chained.

Something Like `Track.objects.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`

Исключить поля

exclude_fields(columns: Union[List, str, set, dict]) -> QuerySet

С помощью except_fields () можно выбрать подгруппу столбцов модели, которые будут исключены для ограничения загрузки данных.

Это противоречит методу fields(), поэтому проверьте документацию выше, чтобы узнать, какие параметры доступны.

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

Обратите внимание на то, что fields() и except_fields () применяются как к главной модели (в обычных запросах, таких как get, all и т. д.), так и к моделям select_lated и prefetch_lated (с использованием вложенных представлений).

Ниже вы можете найти несколько простых примеров:

  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
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import asyncio

import databases
import ormar
import sqlalchemy
from examples import create_drop_database
from tests.settings import DATABASE_URL

base_ormar_config = ormar.OrmarConfig(
    database=databases.Database(DATABASE_URL, force_rollback=True),
    metadata=sqlalchemy.MetaData(),
)


class Company(ormar.Model):
    ormar_config = base_ormar_config.copy(tablename="companies")

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


class Car(ormar.Model):
    ormar_config = base_ormar_config.copy()

    id: int = ormar.Integer(primary_key=True)
    manufacturer = ormar.ForeignKey(Company)
    name: str = ormar.String(max_length=100)
    year: int = ormar.Integer(nullable=True)
    gearbox_type: str = ormar.String(max_length=20, nullable=True)
    gears: int = ormar.Integer(nullable=True)
    aircon_type: str = ormar.String(max_length=20, nullable=True)


@create_drop_database(base_config=base_ormar_config)
async def sample_data():
    # build some sample data
    toyota = await Company.objects.create(name="Toyota", founded=1937)
    await Car.objects.create(
        manufacturer=toyota,
        name="Corolla",
        year=2020,
        gearbox_type="Manual",
        gears=5,
        aircon_type="Manual",
    )
    await Car.objects.create(
        manufacturer=toyota,
        name="Yaris",
        year=2019,
        gearbox_type="Manual",
        gears=5,
        aircon_type="Manual",
    )
    await Car.objects.create(
        manufacturer=toyota,
        name="Supreme",
        year=2020,
        gearbox_type="Auto",
        gears=6,
        aircon_type="Auto",
    )


asyncio.run(sample_data())


# select manufacturer but only name,
# to include related models use notation {model_name}__{column}
all_cars = await (
    Car.objects
    .select_related('manufacturer')
    .exclude_fields([
        'year',
        'gearbox_type',
        'gears',
        'aircon_type',
        'company__founded'
    ])
    .all()
)
for car in all_cars:
    # excluded columns will yield None
    assert all(getattr(car, x) is None
               for x in [
                   'year',
                   'gearbox_type',
                   'gears',
                   'aircon_type'
               ])
    # included column on related models will be available,
    # pk column is always included
    # even if you do not include it in fields list
    assert car.manufacturer.name == 'Toyota'
    # also in the nested related models,
    # you cannot exclude pk - it's always auto added
    assert car.manufacturer.founded is None

# fields() can be called several times,
# building up the columns to select
# models included in select_related 
# but with no columns in fields list implies all fields
all_cars = await (
    Car.objects
    .select_related('manufacturer')
    .exclude_fields('year')
    .exclude_fields(['gear', 'gearbox_type'])
    .all()
)
# all fields from company model are selected
assert all_cars[0].manufacturer.name == 'Toyota'
assert all_cars[0].manufacturer.founded == 1937

# cannot exclude mandatory model columns,
# company__name in this example - note usage of dict/set this time
await (
    Car.objects
    .select_related('manufacturer')
    .exclude_fields([{'company': {'name'}}])
    .all()
)
# will raise pydantic ValidationError as company.name is required

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

1
2
Метод `values()` может быть использован для извлечения данных из mandatory fields, though data will
Будьте ретушенны как `dict`.

!!! Столбец Pk не может быть исключен-он всегда добавляется автоматически, даже если явно исключается.

!!!Обратите внимание, что все методы, которые не возвращают строки, явно возвращают экземпляр 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()`

Метод QuerysetProxy

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

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

Область применения

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

Tip

Исключить поля

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

Tip