strapi-kit 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- strapi_kit/__init__.py +97 -0
- strapi_kit/__version__.py +15 -0
- strapi_kit/_version.py +34 -0
- strapi_kit/auth/__init__.py +7 -0
- strapi_kit/auth/api_token.py +48 -0
- strapi_kit/cache/__init__.py +5 -0
- strapi_kit/cache/schema_cache.py +211 -0
- strapi_kit/client/__init__.py +11 -0
- strapi_kit/client/async_client.py +1032 -0
- strapi_kit/client/base.py +460 -0
- strapi_kit/client/sync_client.py +980 -0
- strapi_kit/config_provider.py +368 -0
- strapi_kit/exceptions/__init__.py +37 -0
- strapi_kit/exceptions/errors.py +205 -0
- strapi_kit/export/__init__.py +10 -0
- strapi_kit/export/exporter.py +384 -0
- strapi_kit/export/importer.py +619 -0
- strapi_kit/export/media_handler.py +322 -0
- strapi_kit/export/relation_resolver.py +172 -0
- strapi_kit/models/__init__.py +104 -0
- strapi_kit/models/bulk.py +69 -0
- strapi_kit/models/config.py +174 -0
- strapi_kit/models/enums.py +97 -0
- strapi_kit/models/export_format.py +166 -0
- strapi_kit/models/import_options.py +142 -0
- strapi_kit/models/request/__init__.py +1 -0
- strapi_kit/models/request/fields.py +65 -0
- strapi_kit/models/request/filters.py +611 -0
- strapi_kit/models/request/pagination.py +168 -0
- strapi_kit/models/request/populate.py +281 -0
- strapi_kit/models/request/query.py +429 -0
- strapi_kit/models/request/sort.py +147 -0
- strapi_kit/models/response/__init__.py +1 -0
- strapi_kit/models/response/base.py +75 -0
- strapi_kit/models/response/component.py +67 -0
- strapi_kit/models/response/media.py +91 -0
- strapi_kit/models/response/meta.py +44 -0
- strapi_kit/models/response/normalized.py +168 -0
- strapi_kit/models/response/relation.py +48 -0
- strapi_kit/models/response/v4.py +70 -0
- strapi_kit/models/response/v5.py +57 -0
- strapi_kit/models/schema.py +93 -0
- strapi_kit/operations/__init__.py +16 -0
- strapi_kit/operations/media.py +226 -0
- strapi_kit/operations/streaming.py +144 -0
- strapi_kit/parsers/__init__.py +5 -0
- strapi_kit/parsers/version_detecting.py +171 -0
- strapi_kit/protocols.py +455 -0
- strapi_kit/utils/__init__.py +15 -0
- strapi_kit/utils/rate_limiter.py +201 -0
- strapi_kit/utils/uid.py +88 -0
- strapi_kit-0.0.1.dist-info/METADATA +1098 -0
- strapi_kit-0.0.1.dist-info/RECORD +55 -0
- strapi_kit-0.0.1.dist-info/WHEEL +4 -0
- strapi_kit-0.0.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"""Pagination configuration for Strapi API queries.
|
|
2
|
+
|
|
3
|
+
Strapi supports two pagination strategies:
|
|
4
|
+
1. Page-based: Use page number and page size
|
|
5
|
+
2. Offset-based: Use start offset and limit
|
|
6
|
+
|
|
7
|
+
IMPORTANT: Cannot mix pagination strategies in the same query.
|
|
8
|
+
|
|
9
|
+
Examples:
|
|
10
|
+
Page-based pagination:
|
|
11
|
+
>>> pagination = PagePagination(page=1, page_size=25)
|
|
12
|
+
>>> pagination.to_query_dict()
|
|
13
|
+
{'pagination[page]': 1, 'pagination[pageSize]': 25, 'pagination[withCount]': True}
|
|
14
|
+
|
|
15
|
+
Offset-based pagination:
|
|
16
|
+
>>> pagination = OffsetPagination(start=0, limit=25)
|
|
17
|
+
>>> pagination.to_query_dict()
|
|
18
|
+
{'pagination[start]': 0, 'pagination[limit]': 25, 'pagination[withCount]': True}
|
|
19
|
+
|
|
20
|
+
Disable count (performance optimization):
|
|
21
|
+
>>> pagination = PagePagination(page=1, page_size=100, with_count=False)
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
from pydantic import BaseModel, Field, field_validator
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PagePagination(BaseModel):
|
|
30
|
+
"""Page-based pagination configuration.
|
|
31
|
+
|
|
32
|
+
Uses page number and page size for pagination. This is the most
|
|
33
|
+
user-friendly approach for displaying results across multiple pages.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
page: Page number (1-indexed, must be >= 1)
|
|
37
|
+
page_size: Number of items per page (must be between 1 and 100)
|
|
38
|
+
with_count: Include total count in response (default: True)
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
page: int = Field(default=1, ge=1, description="Page number (1-indexed)")
|
|
42
|
+
page_size: int = Field(default=25, ge=1, le=100, description="Items per page")
|
|
43
|
+
with_count: bool = Field(default=True, description="Include total count in response metadata")
|
|
44
|
+
|
|
45
|
+
@field_validator("page")
|
|
46
|
+
@classmethod
|
|
47
|
+
def validate_page(cls, v: int) -> int:
|
|
48
|
+
"""Validate page number is positive.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
v: Page number to validate
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Validated page number
|
|
55
|
+
|
|
56
|
+
Raises:
|
|
57
|
+
ValueError: If page number is less than 1
|
|
58
|
+
"""
|
|
59
|
+
if v < 1:
|
|
60
|
+
raise ValueError("Page number must be >= 1")
|
|
61
|
+
return v
|
|
62
|
+
|
|
63
|
+
@field_validator("page_size")
|
|
64
|
+
@classmethod
|
|
65
|
+
def validate_page_size(cls, v: int) -> int:
|
|
66
|
+
"""Validate page size is within allowed range.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
v: Page size to validate
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Validated page size
|
|
73
|
+
|
|
74
|
+
Raises:
|
|
75
|
+
ValueError: If page size is out of range [1, 100]
|
|
76
|
+
"""
|
|
77
|
+
if v < 1 or v > 100:
|
|
78
|
+
raise ValueError("Page size must be between 1 and 100")
|
|
79
|
+
return v
|
|
80
|
+
|
|
81
|
+
def to_query_dict(self) -> dict[str, Any]:
|
|
82
|
+
"""Convert to query parameters dictionary.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Dictionary with pagination parameters in Strapi format
|
|
86
|
+
|
|
87
|
+
Examples:
|
|
88
|
+
>>> PagePagination(page=2, page_size=50).to_query_dict()
|
|
89
|
+
{'pagination[page]': 2, 'pagination[pageSize]': 50, 'pagination[withCount]': True}
|
|
90
|
+
"""
|
|
91
|
+
return {
|
|
92
|
+
"pagination[page]": self.page,
|
|
93
|
+
"pagination[pageSize]": self.page_size,
|
|
94
|
+
"pagination[withCount]": self.with_count,
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class OffsetPagination(BaseModel):
|
|
99
|
+
"""Offset-based pagination configuration.
|
|
100
|
+
|
|
101
|
+
Uses start offset and limit for pagination. This approach is more
|
|
102
|
+
flexible but requires manual calculation of offsets.
|
|
103
|
+
|
|
104
|
+
Attributes:
|
|
105
|
+
start: Starting offset (0-indexed, must be >= 0)
|
|
106
|
+
limit: Maximum number of items to return (must be between 1 and 100)
|
|
107
|
+
with_count: Include total count in response (default: True)
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
start: int = Field(default=0, ge=0, description="Starting offset (0-indexed)")
|
|
111
|
+
limit: int = Field(default=25, ge=1, le=100, description="Maximum items to return")
|
|
112
|
+
with_count: bool = Field(default=True, description="Include total count in response metadata")
|
|
113
|
+
|
|
114
|
+
@field_validator("start")
|
|
115
|
+
@classmethod
|
|
116
|
+
def validate_start(cls, v: int) -> int:
|
|
117
|
+
"""Validate start offset is non-negative.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
v: Start offset to validate
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Validated start offset
|
|
124
|
+
|
|
125
|
+
Raises:
|
|
126
|
+
ValueError: If start is negative
|
|
127
|
+
"""
|
|
128
|
+
if v < 0:
|
|
129
|
+
raise ValueError("Start offset must be >= 0")
|
|
130
|
+
return v
|
|
131
|
+
|
|
132
|
+
@field_validator("limit")
|
|
133
|
+
@classmethod
|
|
134
|
+
def validate_limit(cls, v: int) -> int:
|
|
135
|
+
"""Validate limit is within allowed range.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
v: Limit to validate
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Validated limit
|
|
142
|
+
|
|
143
|
+
Raises:
|
|
144
|
+
ValueError: If limit is out of range [1, 100]
|
|
145
|
+
"""
|
|
146
|
+
if v < 1 or v > 100:
|
|
147
|
+
raise ValueError("Limit must be between 1 and 100")
|
|
148
|
+
return v
|
|
149
|
+
|
|
150
|
+
def to_query_dict(self) -> dict[str, Any]:
|
|
151
|
+
"""Convert to query parameters dictionary.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
Dictionary with pagination parameters in Strapi format
|
|
155
|
+
|
|
156
|
+
Examples:
|
|
157
|
+
>>> OffsetPagination(start=50, limit=25).to_query_dict()
|
|
158
|
+
{'pagination[start]': 50, 'pagination[limit]': 25, 'pagination[withCount]': True}
|
|
159
|
+
"""
|
|
160
|
+
return {
|
|
161
|
+
"pagination[start]": self.start,
|
|
162
|
+
"pagination[limit]": self.limit,
|
|
163
|
+
"pagination[withCount]": self.with_count,
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# Type alias for either pagination strategy
|
|
168
|
+
Pagination = PagePagination | OffsetPagination
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"""Population (relation expansion) for Strapi API queries.
|
|
2
|
+
|
|
3
|
+
Strapi supports populating (expanding) relations, components, and dynamic zones.
|
|
4
|
+
This module provides a fluent API for building complex population configurations.
|
|
5
|
+
|
|
6
|
+
Examples:
|
|
7
|
+
Simple population:
|
|
8
|
+
>>> populate = Populate().fields_list(["author", "category"])
|
|
9
|
+
>>> populate.to_query_dict()
|
|
10
|
+
{'populate': ['author', 'category']}
|
|
11
|
+
|
|
12
|
+
Populate all relations:
|
|
13
|
+
>>> populate = Populate().all()
|
|
14
|
+
>>> populate.to_query_dict()
|
|
15
|
+
{'populate': '*'}
|
|
16
|
+
|
|
17
|
+
Nested population with filtering:
|
|
18
|
+
>>> from strapi_kit.models.request.filters import FilterBuilder
|
|
19
|
+
>>> populate = Populate().add_field(
|
|
20
|
+
... "author",
|
|
21
|
+
... fields=["name", "email"],
|
|
22
|
+
... filters=FilterBuilder().eq("active", True)
|
|
23
|
+
... )
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
from typing import Any
|
|
29
|
+
|
|
30
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
31
|
+
|
|
32
|
+
from strapi_kit.models.request.filters import FilterBuilder
|
|
33
|
+
from strapi_kit.models.request.sort import Sort
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class PopulateField(BaseModel):
|
|
37
|
+
"""Configuration for populating a single field.
|
|
38
|
+
|
|
39
|
+
Attributes:
|
|
40
|
+
field: Field name to populate
|
|
41
|
+
nested: Nested population configuration
|
|
42
|
+
filters: Filter conditions for the populated data
|
|
43
|
+
fields: Specific fields to select from the relation
|
|
44
|
+
sort: Sort configuration for the populated data
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
48
|
+
|
|
49
|
+
field: str = Field(..., min_length=1, description="Field name to populate")
|
|
50
|
+
nested: Populate | None = Field(None, description="Nested population")
|
|
51
|
+
filters: FilterBuilder | None = Field(None, description="Filter populated data")
|
|
52
|
+
fields: list[str] | None = Field(None, description="Fields to select")
|
|
53
|
+
sort: Sort | None = Field(None, description="Sort configuration")
|
|
54
|
+
|
|
55
|
+
def to_dict(self, _depth: int = 0, _max_depth: int = 10) -> dict[str, Any]:
|
|
56
|
+
"""Convert to dictionary format for query parameters.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
_depth: Current recursion depth (internal use)
|
|
60
|
+
_max_depth: Maximum allowed recursion depth (default: 10)
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Dictionary with field name as key and configuration as value
|
|
64
|
+
|
|
65
|
+
Raises:
|
|
66
|
+
RecursionError: If nesting exceeds max_depth
|
|
67
|
+
|
|
68
|
+
Examples:
|
|
69
|
+
>>> # Simple populate
|
|
70
|
+
>>> pf = PopulateField(field="author")
|
|
71
|
+
>>> pf.to_dict()
|
|
72
|
+
{'author': {'populate': '*'}}
|
|
73
|
+
|
|
74
|
+
>>> # With field selection
|
|
75
|
+
>>> pf = PopulateField(field="author", fields=["name", "email"])
|
|
76
|
+
>>> pf.to_dict()
|
|
77
|
+
{'author': {'fields': ['name', 'email'], 'populate': '*'}}
|
|
78
|
+
"""
|
|
79
|
+
if _depth > _max_depth:
|
|
80
|
+
raise RecursionError(
|
|
81
|
+
f"Populate nesting exceeded maximum depth of {_max_depth}. "
|
|
82
|
+
"This may indicate circular references in your populate configuration."
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
config: dict[str, Any] = {}
|
|
86
|
+
|
|
87
|
+
# Add field selection
|
|
88
|
+
if self.fields:
|
|
89
|
+
config["fields"] = self.fields
|
|
90
|
+
|
|
91
|
+
# Add filters
|
|
92
|
+
if self.filters:
|
|
93
|
+
filter_dict = self.filters.to_query_dict()
|
|
94
|
+
if filter_dict:
|
|
95
|
+
config["filters"] = filter_dict
|
|
96
|
+
|
|
97
|
+
# Add sort
|
|
98
|
+
if self.sort:
|
|
99
|
+
sort_list = self.sort.to_query_list()
|
|
100
|
+
if sort_list:
|
|
101
|
+
config["sort"] = sort_list
|
|
102
|
+
|
|
103
|
+
# Add nested population
|
|
104
|
+
if self.nested:
|
|
105
|
+
nested_dict = self.nested.to_query_dict(_depth=_depth + 1, _max_depth=_max_depth)
|
|
106
|
+
if "populate" in nested_dict:
|
|
107
|
+
config["populate"] = nested_dict["populate"]
|
|
108
|
+
else:
|
|
109
|
+
# Default: populate all fields of this relation
|
|
110
|
+
config["populate"] = "*"
|
|
111
|
+
|
|
112
|
+
return {self.field: config}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class Populate:
|
|
116
|
+
"""Fluent API for building population configurations.
|
|
117
|
+
|
|
118
|
+
Strapi population allows expanding relations, components, and dynamic zones.
|
|
119
|
+
This class provides methods to configure simple and complex population scenarios.
|
|
120
|
+
|
|
121
|
+
Examples:
|
|
122
|
+
>>> # Populate all relations
|
|
123
|
+
>>> populate = Populate().all()
|
|
124
|
+
|
|
125
|
+
>>> # Populate specific fields
|
|
126
|
+
>>> populate = Populate().fields_list(["author", "category"])
|
|
127
|
+
|
|
128
|
+
>>> # Populate with nested relations
|
|
129
|
+
>>> populate = (Populate()
|
|
130
|
+
... .add_field("author")
|
|
131
|
+
... .add_field("posts", nested=Populate().add_field("comments")))
|
|
132
|
+
|
|
133
|
+
>>> # Populate with filtering
|
|
134
|
+
>>> populate = Populate().add_field(
|
|
135
|
+
... "author",
|
|
136
|
+
... filters=FilterBuilder().eq("active", True),
|
|
137
|
+
... fields=["name", "email"]
|
|
138
|
+
... )
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
def __init__(self) -> None:
|
|
142
|
+
"""Initialize an empty populate configuration."""
|
|
143
|
+
self._populate_all: bool = False
|
|
144
|
+
self._fields: list[PopulateField] = []
|
|
145
|
+
|
|
146
|
+
def all(self) -> Populate:
|
|
147
|
+
"""Populate all first-level relations.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Self for method chaining
|
|
151
|
+
|
|
152
|
+
Examples:
|
|
153
|
+
>>> populate = Populate().all()
|
|
154
|
+
>>> populate.to_query_dict()
|
|
155
|
+
{'populate': '*'}
|
|
156
|
+
"""
|
|
157
|
+
self._populate_all = True
|
|
158
|
+
return self
|
|
159
|
+
|
|
160
|
+
def fields_list(self, fields: list[str]) -> Populate:
|
|
161
|
+
"""Populate specific fields (simple list).
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
fields: List of field names to populate
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Self for method chaining
|
|
168
|
+
|
|
169
|
+
Examples:
|
|
170
|
+
>>> populate = Populate().fields_list(["author", "category", "tags"])
|
|
171
|
+
>>> populate.to_query_dict()
|
|
172
|
+
{'populate': ['author', 'category', 'tags']}
|
|
173
|
+
"""
|
|
174
|
+
# Convert simple field names to PopulateField objects
|
|
175
|
+
for field_name in fields:
|
|
176
|
+
self._fields.append(
|
|
177
|
+
PopulateField(field=field_name, nested=None, filters=None, fields=None, sort=None)
|
|
178
|
+
)
|
|
179
|
+
return self
|
|
180
|
+
|
|
181
|
+
def add_field(
|
|
182
|
+
self,
|
|
183
|
+
field: str,
|
|
184
|
+
nested: Populate | None = None,
|
|
185
|
+
filters: FilterBuilder | None = None,
|
|
186
|
+
fields: list[str] | None = None,
|
|
187
|
+
sort: Sort | None = None,
|
|
188
|
+
) -> Populate:
|
|
189
|
+
"""Add a field to populate with advanced configuration.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
field: Field name to populate
|
|
193
|
+
nested: Nested population configuration
|
|
194
|
+
filters: Filter conditions for the populated data
|
|
195
|
+
fields: Specific fields to select from the relation
|
|
196
|
+
sort: Sort configuration for the populated data
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
Self for method chaining
|
|
200
|
+
|
|
201
|
+
Examples:
|
|
202
|
+
>>> # Simple field
|
|
203
|
+
>>> populate = Populate().add_field("author")
|
|
204
|
+
|
|
205
|
+
>>> # With field selection
|
|
206
|
+
>>> populate = Populate().add_field("author", fields=["name", "email"])
|
|
207
|
+
|
|
208
|
+
>>> # With filtering
|
|
209
|
+
>>> populate = Populate().add_field(
|
|
210
|
+
... "comments",
|
|
211
|
+
... filters=FilterBuilder().eq("approved", True),
|
|
212
|
+
... sort=Sort().by_field("createdAt", SortDirection.DESC)
|
|
213
|
+
... )
|
|
214
|
+
|
|
215
|
+
>>> # Nested population
|
|
216
|
+
>>> populate = Populate().add_field(
|
|
217
|
+
... "author",
|
|
218
|
+
... nested=Populate().add_field("profile")
|
|
219
|
+
... )
|
|
220
|
+
"""
|
|
221
|
+
self._fields.append(
|
|
222
|
+
PopulateField(field=field, nested=nested, filters=filters, fields=fields, sort=sort)
|
|
223
|
+
)
|
|
224
|
+
return self
|
|
225
|
+
|
|
226
|
+
def to_query_dict(self, _depth: int = 0, _max_depth: int = 10) -> dict[str, Any]:
|
|
227
|
+
"""Convert to dictionary format for query parameters.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
_depth: Current recursion depth (internal use)
|
|
231
|
+
_max_depth: Maximum allowed recursion depth (default: 10)
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Dictionary with 'populate' key
|
|
235
|
+
|
|
236
|
+
Raises:
|
|
237
|
+
RecursionError: If nesting exceeds max_depth
|
|
238
|
+
|
|
239
|
+
Examples:
|
|
240
|
+
>>> # Populate all
|
|
241
|
+
>>> Populate().all().to_query_dict()
|
|
242
|
+
{'populate': '*'}
|
|
243
|
+
|
|
244
|
+
>>> # Simple list
|
|
245
|
+
>>> Populate().fields_list(["author", "category"]).to_query_dict()
|
|
246
|
+
{'populate': ['author', 'category']}
|
|
247
|
+
|
|
248
|
+
>>> # Complex with configuration
|
|
249
|
+
>>> populate = Populate().add_field("author", fields=["name"])
|
|
250
|
+
>>> # Returns nested structure
|
|
251
|
+
"""
|
|
252
|
+
# Check depth limit at Populate level
|
|
253
|
+
if _depth > _max_depth:
|
|
254
|
+
raise RecursionError(
|
|
255
|
+
f"Populate nesting exceeded maximum depth of {_max_depth}. "
|
|
256
|
+
"This may indicate circular references in your populate configuration."
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
if not self._populate_all and not self._fields:
|
|
260
|
+
return {}
|
|
261
|
+
|
|
262
|
+
# Populate all
|
|
263
|
+
if self._populate_all:
|
|
264
|
+
return {"populate": "*"}
|
|
265
|
+
|
|
266
|
+
# Check if all fields are simple (no config)
|
|
267
|
+
all_simple = all(
|
|
268
|
+
not f.nested and not f.filters and not f.fields and not f.sort for f in self._fields
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
if all_simple:
|
|
272
|
+
# Simple array format
|
|
273
|
+
return {"populate": [f.field for f in self._fields]}
|
|
274
|
+
|
|
275
|
+
# Complex object format
|
|
276
|
+
result: dict[str, Any] = {}
|
|
277
|
+
for field_config in self._fields:
|
|
278
|
+
field_dict = field_config.to_dict(_depth=_depth, _max_depth=_max_depth)
|
|
279
|
+
result.update(field_dict)
|
|
280
|
+
|
|
281
|
+
return {"populate": result}
|