Выбор подгруппы столбцов
Для выбора только выбранных столбцов в модели можно использовать следующие функции.
-
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, поля, необходимые для исключения, должны быть пустыми.
| Метод `values()` может быть использован для извлечения данных из mandatory fields, though data will
Be Returned as a `dict`.
|
Вы не можете исключить обязательный столбец типа-имя производителя__в данном примере.
| Авариум (
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, чтобы можно было связать их друг с другом
| 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. Для исключения поля оно должно быть пустым.
| Метод `values()` может быть использован для извлечения данных из mandatory fields, though data will
Будьте ретушенны как `dict`.
|
!!! Столбец Pk не может быть исключен-он всегда добавляется автоматически, даже если явно исключается.
!!!Обратите внимание, что все методы, которые не возвращают строки, явно возвращают экземпляр QuerySet, чтобы можно было связать их друг с другом
| 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, поэтому вы можете фильтровать, создавать и выбирать связанные модели непосредственно из родительской модели.
Область применения
То же самое, что и поля, приведенные выше, но позволяет выбрать столбец из связанного объекта на другом конце отношения.
Исключить поля
То же самое, что и функция except_fields выше, но позволяет выбрать столбец из связанных объектов на другом конце отношения.