chub-dev 0.1.0 → 0.1.2-beta.0
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.
- package/README.md +55 -0
- package/bin/chub-mcp +2 -0
- package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
- package/dist/airtable/docs/database/python/DOC.md +1735 -0
- package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
- package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
- package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
- package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
- package/dist/asana/docs/tasks/DOC.md +1396 -0
- package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
- package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
- package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
- package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
- package/dist/auth0/docs/identity/python/DOC.md +1199 -0
- package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
- package/dist/aws/docs/s3/python/DOC.md +1807 -0
- package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
- package/dist/binance/docs/trading/python/DOC.md +1454 -0
- package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
- package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
- package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
- package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
- package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
- package/dist/clerk/docs/auth/python/DOC.md +274 -0
- package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
- package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
- package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
- package/dist/cohere/docs/llm/DOC.md +1335 -0
- package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
- package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
- package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
- package/dist/deepgram/docs/speech/python/DOC.md +685 -0
- package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
- package/dist/deepl/docs/translation/python/DOC.md +944 -0
- package/dist/deepseek/docs/llm/DOC.md +1220 -0
- package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
- package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
- package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
- package/dist/discord/docs/bot/python/DOC.md +1130 -0
- package/dist/elasticsearch/docs/search/DOC.md +1634 -0
- package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
- package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
- package/dist/firebase/docs/auth/DOC.md +1015 -0
- package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
- package/dist/gemini/docs/genai/python/DOC.md +555 -0
- package/dist/github/docs/octokit/DOC.md +1560 -0
- package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
- package/dist/google/docs/bigquery/python/DOC.md +1503 -0
- package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
- package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
- package/dist/huggingface/docs/transformers/DOC.md +948 -0
- package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
- package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
- package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
- package/dist/jira/docs/issues/python/DOC.md +1492 -0
- package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
- package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
- package/dist/landingai-ade/docs/api/DOC.md +620 -0
- package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
- package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
- package/dist/landingai-ade/skills/SKILL.md +489 -0
- package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
- package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
- package/dist/linear/docs/tracker/DOC.md +1554 -0
- package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
- package/dist/livekit/docs/realtime/python/DOC.md +163 -0
- package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
- package/dist/meilisearch/docs/search/DOC.md +1241 -0
- package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
- package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
- package/dist/mongodb/docs/atlas/DOC.md +2041 -0
- package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
- package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
- package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
- package/dist/okta/docs/identity/python/DOC.md +1401 -0
- package/dist/openai/docs/chat/javascript/DOC.md +407 -0
- package/dist/openai/docs/chat/python/DOC.md +568 -0
- package/dist/paypal/docs/checkout/DOC.md +278 -0
- package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
- package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
- package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
- package/dist/plaid/docs/banking/python/DOC.md +1203 -0
- package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
- package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
- package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
- package/dist/prisma/docs/orm/python/DOC.md +1317 -0
- package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
- package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
- package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
- package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
- package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
- package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
- package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
- package/dist/redis/docs/key-value/python/DOC.md +2054 -0
- package/dist/registry.json +2817 -0
- package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
- package/dist/resend/docs/email/DOC.md +1271 -0
- package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
- package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
- package/dist/search-index.json +1 -0
- package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
- package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
- package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
- package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
- package/dist/shopify/docs/storefront/DOC.md +457 -0
- package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
- package/dist/slack/docs/workspace/python/DOC.md +271 -0
- package/dist/square/docs/payments/javascript/DOC.md +1855 -0
- package/dist/square/docs/payments/python/DOC.md +1728 -0
- package/dist/stripe/docs/api/DOC.md +1727 -0
- package/dist/stripe/docs/payments/DOC.md +1726 -0
- package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
- package/dist/stytch/docs/auth/python/DOC.md +1962 -0
- package/dist/supabase/docs/client/DOC.md +1606 -0
- package/dist/twilio/docs/messaging/python/DOC.md +469 -0
- package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
- package/dist/vercel/docs/platform/DOC.md +1940 -0
- package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
- package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
- package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
- package/dist/zendesk/docs/support/python/DOC.md +2297 -0
- package/package.json +22 -6
- package/skills/get-api-docs/SKILL.md +84 -0
- package/src/commands/annotate.js +83 -0
- package/src/commands/build.js +12 -1
- package/src/commands/feedback.js +150 -0
- package/src/commands/get.js +83 -42
- package/src/commands/search.js +7 -0
- package/src/index.js +43 -17
- package/src/lib/analytics.js +90 -0
- package/src/lib/annotations.js +57 -0
- package/src/lib/bm25.js +170 -0
- package/src/lib/cache.js +69 -6
- package/src/lib/config.js +8 -3
- package/src/lib/identity.js +99 -0
- package/src/lib/registry.js +103 -20
- package/src/lib/telemetry.js +86 -0
- package/src/mcp/server.js +177 -0
- package/src/mcp/tools.js +251 -0
|
@@ -0,0 +1,1276 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: headless-cms
|
|
3
|
+
description: "Directus Python SDK coding guidelines for interacting with Directus projects using the py-directus library"
|
|
4
|
+
metadata:
|
|
5
|
+
languages: "python"
|
|
6
|
+
versions: "0.0.30"
|
|
7
|
+
updated-on: "2026-03-02"
|
|
8
|
+
source: maintainer
|
|
9
|
+
tags: "directus,headless-cms,api,content,backend"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Directus Python SDK Coding Guidelines
|
|
13
|
+
|
|
14
|
+
You are a Directus Python SDK coding expert. Help me with writing code using the Directus Python SDK calling the official libraries.
|
|
15
|
+
|
|
16
|
+
You can find the official SDK documentation and code samples here:
|
|
17
|
+
https://panos-stavrianos.github.io/py-directus/
|
|
18
|
+
|
|
19
|
+
## Golden Rule: Use the Correct and Current SDK
|
|
20
|
+
|
|
21
|
+
Always use the py-directus library to interact with Directus projects in Python. This is a community-maintained async Python wrapper for the Directus API. Do not use outdated or unmaintained libraries.
|
|
22
|
+
|
|
23
|
+
- **Library Name:** py-directus
|
|
24
|
+
- **PyPI Package:** `py-directus`
|
|
25
|
+
- **Alternative Libraries:** `directus-sdk-py`, `pydirectus-sdk` (less maintained)
|
|
26
|
+
|
|
27
|
+
**Installation:**
|
|
28
|
+
|
|
29
|
+
- **Correct:** `pip install py-directus`
|
|
30
|
+
- **Incorrect:** `pip install directus`
|
|
31
|
+
- **Incorrect:** `pip install directus-python`
|
|
32
|
+
|
|
33
|
+
**APIs and Usage:**
|
|
34
|
+
|
|
35
|
+
- **Correct:** `from py_directus import Directus`
|
|
36
|
+
- **Correct:** `directus = await Directus(url, email, password)`
|
|
37
|
+
- **Correct:** `await directus.collection("articles").read()`
|
|
38
|
+
- **Incorrect:** `DirectusClient` or `DirectusAPI`
|
|
39
|
+
- **Incorrect:** Synchronous API calls without `await`
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
Install py-directus using pip:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install py-directus
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Initialization and Authentication
|
|
50
|
+
|
|
51
|
+
The `py-directus` library is fully asynchronous and requires using `async`/`await` syntax. The library requires creating a Directus instance with authentication.
|
|
52
|
+
|
|
53
|
+
### Authentication with Email and Password
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from py_directus import Directus
|
|
57
|
+
|
|
58
|
+
async def main():
|
|
59
|
+
directus = await Directus(
|
|
60
|
+
url="https://your-directus-instance.com",
|
|
61
|
+
email="user@example.com",
|
|
62
|
+
password="your-password"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Use directus client
|
|
66
|
+
# ...
|
|
67
|
+
|
|
68
|
+
# Run the async function
|
|
69
|
+
import asyncio
|
|
70
|
+
asyncio.run(main())
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Authentication with Static Token
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from py_directus import Directus
|
|
77
|
+
|
|
78
|
+
async def main():
|
|
79
|
+
directus = await Directus(
|
|
80
|
+
url="https://your-directus-instance.com",
|
|
81
|
+
token="your-static-token"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Use directus client
|
|
85
|
+
|
|
86
|
+
import asyncio
|
|
87
|
+
asyncio.run(main())
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Using Context Manager
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from py_directus import Directus
|
|
94
|
+
|
|
95
|
+
async def main():
|
|
96
|
+
async with await Directus(
|
|
97
|
+
url="https://your-directus-instance.com",
|
|
98
|
+
email="user@example.com",
|
|
99
|
+
password="your-password"
|
|
100
|
+
) as directus:
|
|
101
|
+
# Use directus client
|
|
102
|
+
users = await directus.collection("directus_users").read()
|
|
103
|
+
|
|
104
|
+
import asyncio
|
|
105
|
+
asyncio.run(main())
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### With Environment Variables
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import os
|
|
112
|
+
from py_directus import Directus
|
|
113
|
+
|
|
114
|
+
async def main():
|
|
115
|
+
directus = await Directus(
|
|
116
|
+
url=os.getenv("DIRECTUS_URL"),
|
|
117
|
+
token=os.getenv("DIRECTUS_TOKEN")
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Use directus client
|
|
121
|
+
|
|
122
|
+
import asyncio
|
|
123
|
+
asyncio.run(main())
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Reading Items from Collections
|
|
127
|
+
|
|
128
|
+
### Read All Items
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from py_directus import Directus
|
|
132
|
+
|
|
133
|
+
async def main():
|
|
134
|
+
directus = await Directus(
|
|
135
|
+
url="https://your-directus-instance.com",
|
|
136
|
+
token="your-token"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# Read all items from a collection
|
|
140
|
+
response = await directus.collection("articles").read()
|
|
141
|
+
articles = response.items
|
|
142
|
+
|
|
143
|
+
for article in articles:
|
|
144
|
+
print(article)
|
|
145
|
+
|
|
146
|
+
import asyncio
|
|
147
|
+
asyncio.run(main())
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Read Single Item
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from py_directus import Directus
|
|
154
|
+
|
|
155
|
+
async def main():
|
|
156
|
+
directus = await Directus(
|
|
157
|
+
url="https://your-directus-instance.com",
|
|
158
|
+
token="your-token"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Read single item by ID
|
|
162
|
+
response = await directus.collection("articles").read(id="1")
|
|
163
|
+
article = response.item
|
|
164
|
+
|
|
165
|
+
print(article)
|
|
166
|
+
|
|
167
|
+
import asyncio
|
|
168
|
+
asyncio.run(main())
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Read with Field Selection
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from py_directus import Directus
|
|
175
|
+
|
|
176
|
+
async def main():
|
|
177
|
+
directus = await Directus(
|
|
178
|
+
url="https://your-directus-instance.com",
|
|
179
|
+
token="your-token"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Select specific fields
|
|
183
|
+
response = await directus.collection("articles").fields("id", "title", "author.name").read()
|
|
184
|
+
articles = response.items
|
|
185
|
+
|
|
186
|
+
import asyncio
|
|
187
|
+
asyncio.run(main())
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Read with Limit and Offset
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
from py_directus import Directus
|
|
194
|
+
|
|
195
|
+
async def main():
|
|
196
|
+
directus = await Directus(
|
|
197
|
+
url="https://your-directus-instance.com",
|
|
198
|
+
token="your-token"
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# Pagination
|
|
202
|
+
response = await directus.collection("articles").limit(10).offset(20).read()
|
|
203
|
+
articles = response.items
|
|
204
|
+
|
|
205
|
+
import asyncio
|
|
206
|
+
asyncio.run(main())
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Filtering Items
|
|
210
|
+
|
|
211
|
+
### Simple Filter
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
from py_directus import Directus
|
|
215
|
+
|
|
216
|
+
async def main():
|
|
217
|
+
directus = await Directus(
|
|
218
|
+
url="https://your-directus-instance.com",
|
|
219
|
+
token="your-token"
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# Filter by field value
|
|
223
|
+
response = await directus.collection("articles").filter(status="published").read()
|
|
224
|
+
articles = response.items
|
|
225
|
+
|
|
226
|
+
import asyncio
|
|
227
|
+
asyncio.run(main())
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Multiple Filters (AND)
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
from py_directus import Directus
|
|
234
|
+
|
|
235
|
+
async def main():
|
|
236
|
+
directus = await Directus(
|
|
237
|
+
url="https://your-directus-instance.com",
|
|
238
|
+
token="your-token"
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
# Multiple filters are combined with AND
|
|
242
|
+
response = await (
|
|
243
|
+
directus.collection("articles")
|
|
244
|
+
.filter(status="published")
|
|
245
|
+
.filter(views__gte=1000)
|
|
246
|
+
.read()
|
|
247
|
+
)
|
|
248
|
+
articles = response.items
|
|
249
|
+
|
|
250
|
+
import asyncio
|
|
251
|
+
asyncio.run(main())
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Complex Filters with F Object
|
|
255
|
+
|
|
256
|
+
```python
|
|
257
|
+
from py_directus import Directus, F
|
|
258
|
+
|
|
259
|
+
async def main():
|
|
260
|
+
directus = await Directus(
|
|
261
|
+
url="https://your-directus-instance.com",
|
|
262
|
+
token="your-token"
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# OR conditions
|
|
266
|
+
response = await (
|
|
267
|
+
directus.collection("users")
|
|
268
|
+
.filter(F(first_name="John") | F(first_name="Jane"))
|
|
269
|
+
.read()
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
# Complex nested conditions
|
|
273
|
+
response = await (
|
|
274
|
+
directus.collection("articles")
|
|
275
|
+
.filter(
|
|
276
|
+
(F(status="published") | F(status="archived"))
|
|
277
|
+
& F(views__gte=100)
|
|
278
|
+
)
|
|
279
|
+
.read()
|
|
280
|
+
)
|
|
281
|
+
articles = response.items
|
|
282
|
+
|
|
283
|
+
import asyncio
|
|
284
|
+
asyncio.run(main())
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Filter Operators
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
from py_directus import Directus
|
|
291
|
+
|
|
292
|
+
async def main():
|
|
293
|
+
directus = await Directus(
|
|
294
|
+
url="https://your-directus-instance.com",
|
|
295
|
+
token="your-token"
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
# Greater than
|
|
299
|
+
response = await directus.collection("articles").filter(views__gt=1000).read()
|
|
300
|
+
|
|
301
|
+
# Greater than or equal
|
|
302
|
+
response = await directus.collection("articles").filter(views__gte=1000).read()
|
|
303
|
+
|
|
304
|
+
# Less than
|
|
305
|
+
response = await directus.collection("articles").filter(views__lt=1000).read()
|
|
306
|
+
|
|
307
|
+
# Less than or equal
|
|
308
|
+
response = await directus.collection("articles").filter(views__lte=1000).read()
|
|
309
|
+
|
|
310
|
+
# Not equal
|
|
311
|
+
response = await directus.collection("articles").filter(status__neq="draft").read()
|
|
312
|
+
|
|
313
|
+
# Contains
|
|
314
|
+
response = await directus.collection("articles").filter(title__contains="directus").read()
|
|
315
|
+
|
|
316
|
+
# In list
|
|
317
|
+
response = await directus.collection("articles").filter(status__in=["published", "archived"]).read()
|
|
318
|
+
|
|
319
|
+
# Not in list
|
|
320
|
+
response = await directus.collection("articles").filter(status__nin=["draft", "deleted"]).read()
|
|
321
|
+
|
|
322
|
+
# Is null
|
|
323
|
+
response = await directus.collection("articles").filter(author__null=True).read()
|
|
324
|
+
|
|
325
|
+
# Is not null
|
|
326
|
+
response = await directus.collection("articles").filter(author__nnull=True).read()
|
|
327
|
+
|
|
328
|
+
import asyncio
|
|
329
|
+
asyncio.run(main())
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Sorting Items
|
|
333
|
+
|
|
334
|
+
### Single Sort
|
|
335
|
+
|
|
336
|
+
```python
|
|
337
|
+
from py_directus import Directus
|
|
338
|
+
|
|
339
|
+
async def main():
|
|
340
|
+
directus = await Directus(
|
|
341
|
+
url="https://your-directus-instance.com",
|
|
342
|
+
token="your-token"
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
# Sort ascending
|
|
346
|
+
response = await directus.collection("articles").sort("title").read()
|
|
347
|
+
|
|
348
|
+
# Sort descending
|
|
349
|
+
response = await directus.collection("articles").sort("-publish_date").read()
|
|
350
|
+
|
|
351
|
+
import asyncio
|
|
352
|
+
asyncio.run(main())
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Multiple Sorts
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
from py_directus import Directus
|
|
359
|
+
|
|
360
|
+
async def main():
|
|
361
|
+
directus = await Directus(
|
|
362
|
+
url="https://your-directus-instance.com",
|
|
363
|
+
token="your-token"
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
# Multiple sort fields
|
|
367
|
+
response = await directus.collection("articles").sort("-publish_date", "title").read()
|
|
368
|
+
|
|
369
|
+
import asyncio
|
|
370
|
+
asyncio.run(main())
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Searching Items
|
|
374
|
+
|
|
375
|
+
```python
|
|
376
|
+
from py_directus import Directus
|
|
377
|
+
|
|
378
|
+
async def main():
|
|
379
|
+
directus = await Directus(
|
|
380
|
+
url="https://your-directus-instance.com",
|
|
381
|
+
token="your-token"
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
# Full-text search
|
|
385
|
+
response = await directus.collection("articles").search("directus cms").read()
|
|
386
|
+
articles = response.items
|
|
387
|
+
|
|
388
|
+
import asyncio
|
|
389
|
+
asyncio.run(main())
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## Creating Items
|
|
393
|
+
|
|
394
|
+
### Create Single Item
|
|
395
|
+
|
|
396
|
+
```python
|
|
397
|
+
from py_directus import Directus
|
|
398
|
+
|
|
399
|
+
async def main():
|
|
400
|
+
directus = await Directus(
|
|
401
|
+
url="https://your-directus-instance.com",
|
|
402
|
+
token="your-token"
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
# Create a new item
|
|
406
|
+
new_article = {
|
|
407
|
+
"title": "New Article",
|
|
408
|
+
"content": "Article content here",
|
|
409
|
+
"status": "draft"
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
response = await directus.collection("articles").create(new_article)
|
|
413
|
+
created_article = response.item
|
|
414
|
+
|
|
415
|
+
print(f"Created article with ID: {created_article['id']}")
|
|
416
|
+
|
|
417
|
+
import asyncio
|
|
418
|
+
asyncio.run(main())
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### Create Multiple Items
|
|
422
|
+
|
|
423
|
+
```python
|
|
424
|
+
from py_directus import Directus
|
|
425
|
+
|
|
426
|
+
async def main():
|
|
427
|
+
directus = await Directus(
|
|
428
|
+
url="https://your-directus-instance.com",
|
|
429
|
+
token="your-token"
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
# Create multiple items
|
|
433
|
+
new_articles = [
|
|
434
|
+
{"title": "Article 1", "status": "draft"},
|
|
435
|
+
{"title": "Article 2", "status": "draft"},
|
|
436
|
+
{"title": "Article 3", "status": "published"}
|
|
437
|
+
]
|
|
438
|
+
|
|
439
|
+
response = await directus.collection("articles").create(new_articles)
|
|
440
|
+
created_articles = response.items
|
|
441
|
+
|
|
442
|
+
import asyncio
|
|
443
|
+
asyncio.run(main())
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## Updating Items
|
|
447
|
+
|
|
448
|
+
### Update Single Item
|
|
449
|
+
|
|
450
|
+
```python
|
|
451
|
+
from py_directus import Directus
|
|
452
|
+
|
|
453
|
+
async def main():
|
|
454
|
+
directus = await Directus(
|
|
455
|
+
url="https://your-directus-instance.com",
|
|
456
|
+
token="your-token"
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
# Update an item by ID
|
|
460
|
+
updated_data = {
|
|
461
|
+
"status": "published",
|
|
462
|
+
"publish_date": "2024-01-15"
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
response = await directus.collection("articles").update("1", updated_data)
|
|
466
|
+
updated_article = response.item
|
|
467
|
+
|
|
468
|
+
import asyncio
|
|
469
|
+
asyncio.run(main())
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Update Multiple Items
|
|
473
|
+
|
|
474
|
+
```python
|
|
475
|
+
from py_directus import Directus
|
|
476
|
+
|
|
477
|
+
async def main():
|
|
478
|
+
directus = await Directus(
|
|
479
|
+
url="https://your-directus-instance.com",
|
|
480
|
+
token="your-token"
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
# Update multiple items by IDs
|
|
484
|
+
item_ids = ["1", "2", "3"]
|
|
485
|
+
updated_data = {"status": "published"}
|
|
486
|
+
|
|
487
|
+
response = await directus.collection("articles").update(item_ids, updated_data)
|
|
488
|
+
updated_articles = response.items
|
|
489
|
+
|
|
490
|
+
import asyncio
|
|
491
|
+
asyncio.run(main())
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
## Deleting Items
|
|
495
|
+
|
|
496
|
+
### Delete Single Item
|
|
497
|
+
|
|
498
|
+
```python
|
|
499
|
+
from py_directus import Directus
|
|
500
|
+
|
|
501
|
+
async def main():
|
|
502
|
+
directus = await Directus(
|
|
503
|
+
url="https://your-directus-instance.com",
|
|
504
|
+
token="your-token"
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
# Delete an item by ID
|
|
508
|
+
await directus.collection("articles").delete("1")
|
|
509
|
+
|
|
510
|
+
import asyncio
|
|
511
|
+
asyncio.run(main())
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### Delete Multiple Items
|
|
515
|
+
|
|
516
|
+
```python
|
|
517
|
+
from py_directus import Directus
|
|
518
|
+
|
|
519
|
+
async def main():
|
|
520
|
+
directus = await Directus(
|
|
521
|
+
url="https://your-directus-instance.com",
|
|
522
|
+
token="your-token"
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
# Delete multiple items by IDs
|
|
526
|
+
await directus.collection("articles").delete(["1", "2", "3"])
|
|
527
|
+
|
|
528
|
+
import asyncio
|
|
529
|
+
asyncio.run(main())
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
## Aggregation
|
|
533
|
+
|
|
534
|
+
### Count Items
|
|
535
|
+
|
|
536
|
+
```python
|
|
537
|
+
from py_directus import Directus
|
|
538
|
+
|
|
539
|
+
async def main():
|
|
540
|
+
directus = await Directus(
|
|
541
|
+
url="https://your-directus-instance.com",
|
|
542
|
+
token="your-token"
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
# Count all items
|
|
546
|
+
response = await directus.collection("articles").aggregate(count="id").read()
|
|
547
|
+
total_count = response.items[0]["count"]["id"]
|
|
548
|
+
|
|
549
|
+
print(f"Total articles: {total_count}")
|
|
550
|
+
|
|
551
|
+
import asyncio
|
|
552
|
+
asyncio.run(main())
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Count Distinct
|
|
556
|
+
|
|
557
|
+
```python
|
|
558
|
+
from py_directus import Directus
|
|
559
|
+
|
|
560
|
+
async def main():
|
|
561
|
+
directus = await Directus(
|
|
562
|
+
url="https://your-directus-instance.com",
|
|
563
|
+
token="your-token"
|
|
564
|
+
)
|
|
565
|
+
|
|
566
|
+
# Count distinct values
|
|
567
|
+
response = await directus.collection("articles").aggregate(countDistinct="author").read()
|
|
568
|
+
|
|
569
|
+
import asyncio
|
|
570
|
+
asyncio.run(main())
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### Sum, Average, Min, Max
|
|
574
|
+
|
|
575
|
+
```python
|
|
576
|
+
from py_directus import Directus
|
|
577
|
+
|
|
578
|
+
async def main():
|
|
579
|
+
directus = await Directus(
|
|
580
|
+
url="https://your-directus-instance.com",
|
|
581
|
+
token="your-token"
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
# Sum
|
|
585
|
+
response = await directus.collection("articles").aggregate(sum="views").read()
|
|
586
|
+
total_views = response.items[0]["sum"]["views"]
|
|
587
|
+
|
|
588
|
+
# Average
|
|
589
|
+
response = await directus.collection("articles").aggregate(avg="views").read()
|
|
590
|
+
avg_views = response.items[0]["avg"]["views"]
|
|
591
|
+
|
|
592
|
+
# Min
|
|
593
|
+
response = await directus.collection("articles").aggregate(min="views").read()
|
|
594
|
+
min_views = response.items[0]["min"]["views"]
|
|
595
|
+
|
|
596
|
+
# Max
|
|
597
|
+
response = await directus.collection("articles").aggregate(max="views").read()
|
|
598
|
+
max_views = response.items[0]["max"]["views"]
|
|
599
|
+
|
|
600
|
+
import asyncio
|
|
601
|
+
asyncio.run(main())
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
### Multiple Aggregations
|
|
605
|
+
|
|
606
|
+
```python
|
|
607
|
+
from py_directus import Directus
|
|
608
|
+
|
|
609
|
+
async def main():
|
|
610
|
+
directus = await Directus(
|
|
611
|
+
url="https://your-directus-instance.com",
|
|
612
|
+
token="your-token"
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
# Chain multiple aggregations
|
|
616
|
+
response = await (
|
|
617
|
+
directus.collection("articles")
|
|
618
|
+
.aggregate(count="id")
|
|
619
|
+
.aggregate(sum="views")
|
|
620
|
+
.aggregate(avg="views")
|
|
621
|
+
.read()
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
result = response.items[0]
|
|
625
|
+
print(f"Count: {result['count']['id']}")
|
|
626
|
+
print(f"Total views: {result['sum']['views']}")
|
|
627
|
+
print(f"Average views: {result['avg']['views']}")
|
|
628
|
+
|
|
629
|
+
import asyncio
|
|
630
|
+
asyncio.run(main())
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
### Aggregation with Agg Class
|
|
634
|
+
|
|
635
|
+
```python
|
|
636
|
+
from py_directus import Directus, Agg, AggregationOperators
|
|
637
|
+
|
|
638
|
+
async def main():
|
|
639
|
+
directus = await Directus(
|
|
640
|
+
url="https://your-directus-instance.com",
|
|
641
|
+
token="your-token"
|
|
642
|
+
)
|
|
643
|
+
|
|
644
|
+
# Using Agg class for aggregations
|
|
645
|
+
sum_agg = Agg(operator=AggregationOperators.Sum, fields="amount")
|
|
646
|
+
avg_agg = Agg(operator=AggregationOperators.Avg, fields="amount")
|
|
647
|
+
|
|
648
|
+
response = await (
|
|
649
|
+
directus.collection("transactions")
|
|
650
|
+
.aggregate(sum_agg)
|
|
651
|
+
.aggregate(avg_agg)
|
|
652
|
+
.read()
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
import asyncio
|
|
656
|
+
asyncio.run(main())
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### Group By
|
|
660
|
+
|
|
661
|
+
```python
|
|
662
|
+
from py_directus import Directus
|
|
663
|
+
|
|
664
|
+
async def main():
|
|
665
|
+
directus = await Directus(
|
|
666
|
+
url="https://your-directus-instance.com",
|
|
667
|
+
token="your-token"
|
|
668
|
+
)
|
|
669
|
+
|
|
670
|
+
# Group by single field
|
|
671
|
+
response = await (
|
|
672
|
+
directus.collection("articles")
|
|
673
|
+
.aggregate(count="id")
|
|
674
|
+
.groupby("status")
|
|
675
|
+
.read()
|
|
676
|
+
)
|
|
677
|
+
|
|
678
|
+
# Group by multiple fields
|
|
679
|
+
response = await (
|
|
680
|
+
directus.collection("articles")
|
|
681
|
+
.aggregate(count="id")
|
|
682
|
+
.aggregate(avg="views")
|
|
683
|
+
.groupby("status", "author")
|
|
684
|
+
.read()
|
|
685
|
+
)
|
|
686
|
+
|
|
687
|
+
import asyncio
|
|
688
|
+
asyncio.run(main())
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
## Working with Pydantic Models
|
|
692
|
+
|
|
693
|
+
### Using Built-in Models
|
|
694
|
+
|
|
695
|
+
```python
|
|
696
|
+
from py_directus import Directus, DirectusUser
|
|
697
|
+
|
|
698
|
+
async def main():
|
|
699
|
+
directus = await Directus(
|
|
700
|
+
url="https://your-directus-instance.com",
|
|
701
|
+
token="your-token"
|
|
702
|
+
)
|
|
703
|
+
|
|
704
|
+
# Using DirectusUser model
|
|
705
|
+
response = await (
|
|
706
|
+
directus.collection(DirectusUser)
|
|
707
|
+
.filter(first_name="John")
|
|
708
|
+
.read()
|
|
709
|
+
)
|
|
710
|
+
|
|
711
|
+
# Response items are typed as DirectusUser objects
|
|
712
|
+
user = response.item
|
|
713
|
+
print(user.email)
|
|
714
|
+
print(user.first_name)
|
|
715
|
+
print(user.last_name)
|
|
716
|
+
|
|
717
|
+
import asyncio
|
|
718
|
+
asyncio.run(main())
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
### Creating Custom Pydantic Models
|
|
722
|
+
|
|
723
|
+
```python
|
|
724
|
+
from py_directus import Directus
|
|
725
|
+
from pydantic import BaseModel
|
|
726
|
+
from typing import Optional
|
|
727
|
+
|
|
728
|
+
class Article(BaseModel):
|
|
729
|
+
id: Optional[str] = None
|
|
730
|
+
title: str
|
|
731
|
+
content: str
|
|
732
|
+
status: str
|
|
733
|
+
author: Optional[str] = None
|
|
734
|
+
views: int = 0
|
|
735
|
+
|
|
736
|
+
async def main():
|
|
737
|
+
directus = await Directus(
|
|
738
|
+
url="https://your-directus-instance.com",
|
|
739
|
+
token="your-token"
|
|
740
|
+
)
|
|
741
|
+
|
|
742
|
+
# Using custom model - collection name inferred from class name
|
|
743
|
+
response = await directus.collection(Article).read()
|
|
744
|
+
articles = response.items
|
|
745
|
+
|
|
746
|
+
# Type-safe access
|
|
747
|
+
for article in articles:
|
|
748
|
+
print(article.title)
|
|
749
|
+
print(article.status)
|
|
750
|
+
|
|
751
|
+
import asyncio
|
|
752
|
+
asyncio.run(main())
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
## File Management
|
|
756
|
+
|
|
757
|
+
### Upload File
|
|
758
|
+
|
|
759
|
+
```python
|
|
760
|
+
from py_directus import Directus
|
|
761
|
+
import aiofiles
|
|
762
|
+
|
|
763
|
+
async def main():
|
|
764
|
+
directus = await Directus(
|
|
765
|
+
url="https://your-directus-instance.com",
|
|
766
|
+
token="your-token"
|
|
767
|
+
)
|
|
768
|
+
|
|
769
|
+
# Upload a file
|
|
770
|
+
async with aiofiles.open("image.jpg", "rb") as f:
|
|
771
|
+
file_data = await f.read()
|
|
772
|
+
|
|
773
|
+
response = await directus.upload_file(
|
|
774
|
+
data=file_data,
|
|
775
|
+
filename="image.jpg",
|
|
776
|
+
title="My Image",
|
|
777
|
+
folder="folder-uuid"
|
|
778
|
+
)
|
|
779
|
+
|
|
780
|
+
uploaded_file = response.item
|
|
781
|
+
print(f"Uploaded file ID: {uploaded_file['id']}")
|
|
782
|
+
|
|
783
|
+
import asyncio
|
|
784
|
+
asyncio.run(main())
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
### Read Files
|
|
788
|
+
|
|
789
|
+
```python
|
|
790
|
+
from py_directus import Directus
|
|
791
|
+
|
|
792
|
+
async def main():
|
|
793
|
+
directus = await Directus(
|
|
794
|
+
url="https://your-directus-instance.com",
|
|
795
|
+
token="your-token"
|
|
796
|
+
)
|
|
797
|
+
|
|
798
|
+
# Read all files
|
|
799
|
+
response = await directus.collection("directus_files").read()
|
|
800
|
+
files = response.items
|
|
801
|
+
|
|
802
|
+
# Filter image files
|
|
803
|
+
response = await (
|
|
804
|
+
directus.collection("directus_files")
|
|
805
|
+
.filter(type__starts_with="image/")
|
|
806
|
+
.read()
|
|
807
|
+
)
|
|
808
|
+
|
|
809
|
+
import asyncio
|
|
810
|
+
asyncio.run(main())
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
### Get File URL
|
|
814
|
+
|
|
815
|
+
```python
|
|
816
|
+
from py_directus import Directus
|
|
817
|
+
|
|
818
|
+
async def main():
|
|
819
|
+
directus = await Directus(
|
|
820
|
+
url="https://your-directus-instance.com",
|
|
821
|
+
token="your-token"
|
|
822
|
+
)
|
|
823
|
+
|
|
824
|
+
file_id = "file-uuid"
|
|
825
|
+
|
|
826
|
+
# Construct file URL
|
|
827
|
+
file_url = f"{directus.url}/assets/{file_id}"
|
|
828
|
+
|
|
829
|
+
# With transformations (for images)
|
|
830
|
+
thumbnail_url = f"{directus.url}/assets/{file_id}?width=300&height=300&fit=cover"
|
|
831
|
+
|
|
832
|
+
import asyncio
|
|
833
|
+
asyncio.run(main())
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
## User Management
|
|
837
|
+
|
|
838
|
+
### Read Users
|
|
839
|
+
|
|
840
|
+
```python
|
|
841
|
+
from py_directus import Directus, DirectusUser
|
|
842
|
+
|
|
843
|
+
async def main():
|
|
844
|
+
directus = await Directus(
|
|
845
|
+
url="https://your-directus-instance.com",
|
|
846
|
+
token="your-token"
|
|
847
|
+
)
|
|
848
|
+
|
|
849
|
+
# Read all users
|
|
850
|
+
response = await directus.collection(DirectusUser).read()
|
|
851
|
+
users = response.items
|
|
852
|
+
|
|
853
|
+
# Filter active users
|
|
854
|
+
response = await (
|
|
855
|
+
directus.collection(DirectusUser)
|
|
856
|
+
.filter(status="active")
|
|
857
|
+
.read()
|
|
858
|
+
)
|
|
859
|
+
|
|
860
|
+
import asyncio
|
|
861
|
+
asyncio.run(main())
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
### Get Current User
|
|
865
|
+
|
|
866
|
+
```python
|
|
867
|
+
from py_directus import Directus
|
|
868
|
+
|
|
869
|
+
async def main():
|
|
870
|
+
directus = await Directus(
|
|
871
|
+
url="https://your-directus-instance.com",
|
|
872
|
+
email="user@example.com",
|
|
873
|
+
password="password"
|
|
874
|
+
)
|
|
875
|
+
|
|
876
|
+
# Get current authenticated user
|
|
877
|
+
response = await directus.collection("directus_users").read(id="me")
|
|
878
|
+
current_user = response.item
|
|
879
|
+
|
|
880
|
+
print(f"Logged in as: {current_user['email']}")
|
|
881
|
+
|
|
882
|
+
import asyncio
|
|
883
|
+
asyncio.run(main())
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
### Create User
|
|
887
|
+
|
|
888
|
+
```python
|
|
889
|
+
from py_directus import Directus
|
|
890
|
+
|
|
891
|
+
async def main():
|
|
892
|
+
directus = await Directus(
|
|
893
|
+
url="https://your-directus-instance.com",
|
|
894
|
+
token="your-token"
|
|
895
|
+
)
|
|
896
|
+
|
|
897
|
+
# Create a new user
|
|
898
|
+
new_user = {
|
|
899
|
+
"email": "newuser@example.com",
|
|
900
|
+
"password": "secure-password",
|
|
901
|
+
"role": "role-uuid",
|
|
902
|
+
"first_name": "John",
|
|
903
|
+
"last_name": "Doe",
|
|
904
|
+
"status": "active"
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
response = await directus.collection("directus_users").create(new_user)
|
|
908
|
+
created_user = response.item
|
|
909
|
+
|
|
910
|
+
import asyncio
|
|
911
|
+
asyncio.run(main())
|
|
912
|
+
```
|
|
913
|
+
|
|
914
|
+
### Update User
|
|
915
|
+
|
|
916
|
+
```python
|
|
917
|
+
from py_directus import Directus
|
|
918
|
+
|
|
919
|
+
async def main():
|
|
920
|
+
directus = await Directus(
|
|
921
|
+
url="https://your-directus-instance.com",
|
|
922
|
+
token="your-token"
|
|
923
|
+
)
|
|
924
|
+
|
|
925
|
+
# Update a user
|
|
926
|
+
updated_data = {
|
|
927
|
+
"first_name": "Jane",
|
|
928
|
+
"status": "active"
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
response = await directus.collection("directus_users").update("user-uuid", updated_data)
|
|
932
|
+
|
|
933
|
+
import asyncio
|
|
934
|
+
asyncio.run(main())
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
## Roles and Permissions
|
|
938
|
+
|
|
939
|
+
### Read Roles
|
|
940
|
+
|
|
941
|
+
```python
|
|
942
|
+
from py_directus import Directus
|
|
943
|
+
|
|
944
|
+
async def main():
|
|
945
|
+
directus = await Directus(
|
|
946
|
+
url="https://your-directus-instance.com",
|
|
947
|
+
token="your-token"
|
|
948
|
+
)
|
|
949
|
+
|
|
950
|
+
# Read all roles
|
|
951
|
+
response = await directus.collection("directus_roles").read()
|
|
952
|
+
roles = response.items
|
|
953
|
+
|
|
954
|
+
import asyncio
|
|
955
|
+
asyncio.run(main())
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
### Read Permissions
|
|
959
|
+
|
|
960
|
+
```python
|
|
961
|
+
from py_directus import Directus
|
|
962
|
+
|
|
963
|
+
async def main():
|
|
964
|
+
directus = await Directus(
|
|
965
|
+
url="https://your-directus-instance.com",
|
|
966
|
+
token="your-token"
|
|
967
|
+
)
|
|
968
|
+
|
|
969
|
+
# Read permissions for a specific role
|
|
970
|
+
response = await (
|
|
971
|
+
directus.collection("directus_permissions")
|
|
972
|
+
.filter(role="role-uuid")
|
|
973
|
+
.read()
|
|
974
|
+
)
|
|
975
|
+
permissions = response.items
|
|
976
|
+
|
|
977
|
+
import asyncio
|
|
978
|
+
asyncio.run(main())
|
|
979
|
+
```
|
|
980
|
+
|
|
981
|
+
## Collections and Fields
|
|
982
|
+
|
|
983
|
+
### Read Collections
|
|
984
|
+
|
|
985
|
+
```python
|
|
986
|
+
from py_directus import Directus
|
|
987
|
+
|
|
988
|
+
async def main():
|
|
989
|
+
directus = await Directus(
|
|
990
|
+
url="https://your-directus-instance.com",
|
|
991
|
+
token="your-token"
|
|
992
|
+
)
|
|
993
|
+
|
|
994
|
+
# Get all collections
|
|
995
|
+
response = await directus.collection("directus_collections").read()
|
|
996
|
+
collections = response.items
|
|
997
|
+
|
|
998
|
+
import asyncio
|
|
999
|
+
asyncio.run(main())
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
### Read Fields
|
|
1003
|
+
|
|
1004
|
+
```python
|
|
1005
|
+
from py_directus import Directus
|
|
1006
|
+
|
|
1007
|
+
async def main():
|
|
1008
|
+
directus = await Directus(
|
|
1009
|
+
url="https://your-directus-instance.com",
|
|
1010
|
+
token="your-token"
|
|
1011
|
+
)
|
|
1012
|
+
|
|
1013
|
+
# Get all fields for a collection
|
|
1014
|
+
response = await (
|
|
1015
|
+
directus.collection("directus_fields")
|
|
1016
|
+
.filter(collection="articles")
|
|
1017
|
+
.read()
|
|
1018
|
+
)
|
|
1019
|
+
fields = response.items
|
|
1020
|
+
|
|
1021
|
+
import asyncio
|
|
1022
|
+
asyncio.run(main())
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
## Real-time with WebSockets
|
|
1026
|
+
|
|
1027
|
+
### Subscribe to Collection
|
|
1028
|
+
|
|
1029
|
+
```python
|
|
1030
|
+
from py_directus import Directus
|
|
1031
|
+
|
|
1032
|
+
async def main():
|
|
1033
|
+
directus = await Directus(
|
|
1034
|
+
url="https://your-directus-instance.com",
|
|
1035
|
+
token="your-token"
|
|
1036
|
+
)
|
|
1037
|
+
|
|
1038
|
+
# Subscribe to realtime updates
|
|
1039
|
+
async for message in directus.subscribe("articles"):
|
|
1040
|
+
print(f"Received update: {message}")
|
|
1041
|
+
|
|
1042
|
+
import asyncio
|
|
1043
|
+
asyncio.run(main())
|
|
1044
|
+
```
|
|
1045
|
+
|
|
1046
|
+
### Subscribe with Authentication
|
|
1047
|
+
|
|
1048
|
+
```python
|
|
1049
|
+
from py_directus import Directus
|
|
1050
|
+
|
|
1051
|
+
async def main():
|
|
1052
|
+
directus = await Directus(
|
|
1053
|
+
url="https://your-directus-instance.com",
|
|
1054
|
+
email="user@example.com",
|
|
1055
|
+
password="password"
|
|
1056
|
+
)
|
|
1057
|
+
|
|
1058
|
+
# Subscribe to updates for authenticated user
|
|
1059
|
+
async for message in directus.subscribe("articles", uid=True):
|
|
1060
|
+
event_type = message.get("event")
|
|
1061
|
+
data = message.get("data")
|
|
1062
|
+
|
|
1063
|
+
if event_type == "create":
|
|
1064
|
+
print(f"New article created: {data}")
|
|
1065
|
+
elif event_type == "update":
|
|
1066
|
+
print(f"Article updated: {data}")
|
|
1067
|
+
elif event_type == "delete":
|
|
1068
|
+
print(f"Article deleted: {data}")
|
|
1069
|
+
|
|
1070
|
+
import asyncio
|
|
1071
|
+
asyncio.run(main())
|
|
1072
|
+
```
|
|
1073
|
+
|
|
1074
|
+
## Advanced Query Building
|
|
1075
|
+
|
|
1076
|
+
### Chaining Methods
|
|
1077
|
+
|
|
1078
|
+
```python
|
|
1079
|
+
from py_directus import Directus
|
|
1080
|
+
|
|
1081
|
+
async def main():
|
|
1082
|
+
directus = await Directus(
|
|
1083
|
+
url="https://your-directus-instance.com",
|
|
1084
|
+
token="your-token"
|
|
1085
|
+
)
|
|
1086
|
+
|
|
1087
|
+
# Chain multiple query methods
|
|
1088
|
+
response = await (
|
|
1089
|
+
directus.collection("articles")
|
|
1090
|
+
.fields("id", "title", "author.name", "publish_date")
|
|
1091
|
+
.filter(status="published")
|
|
1092
|
+
.filter(views__gte=1000)
|
|
1093
|
+
.sort("-publish_date")
|
|
1094
|
+
.limit(10)
|
|
1095
|
+
.offset(0)
|
|
1096
|
+
.search("directus")
|
|
1097
|
+
.read()
|
|
1098
|
+
)
|
|
1099
|
+
|
|
1100
|
+
articles = response.items
|
|
1101
|
+
|
|
1102
|
+
import asyncio
|
|
1103
|
+
asyncio.run(main())
|
|
1104
|
+
```
|
|
1105
|
+
|
|
1106
|
+
### Deep Filtering on Relations
|
|
1107
|
+
|
|
1108
|
+
```python
|
|
1109
|
+
from py_directus import Directus
|
|
1110
|
+
|
|
1111
|
+
async def main():
|
|
1112
|
+
directus = await Directus(
|
|
1113
|
+
url="https://your-directus-instance.com",
|
|
1114
|
+
token="your-token"
|
|
1115
|
+
)
|
|
1116
|
+
|
|
1117
|
+
# Filter based on related collection
|
|
1118
|
+
response = await (
|
|
1119
|
+
directus.collection("articles")
|
|
1120
|
+
.filter(author__status="active")
|
|
1121
|
+
.filter(author__verified=True)
|
|
1122
|
+
.read()
|
|
1123
|
+
)
|
|
1124
|
+
|
|
1125
|
+
import asyncio
|
|
1126
|
+
asyncio.run(main())
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
## Error Handling
|
|
1130
|
+
|
|
1131
|
+
```python
|
|
1132
|
+
from py_directus import Directus
|
|
1133
|
+
import httpx
|
|
1134
|
+
|
|
1135
|
+
async def main():
|
|
1136
|
+
try:
|
|
1137
|
+
directus = await Directus(
|
|
1138
|
+
url="https://your-directus-instance.com",
|
|
1139
|
+
token="your-token"
|
|
1140
|
+
)
|
|
1141
|
+
|
|
1142
|
+
response = await directus.collection("articles").read()
|
|
1143
|
+
articles = response.items
|
|
1144
|
+
|
|
1145
|
+
except httpx.HTTPError as e:
|
|
1146
|
+
print(f"HTTP error occurred: {e}")
|
|
1147
|
+
except Exception as e:
|
|
1148
|
+
print(f"An error occurred: {e}")
|
|
1149
|
+
|
|
1150
|
+
import asyncio
|
|
1151
|
+
asyncio.run(main())
|
|
1152
|
+
```
|
|
1153
|
+
|
|
1154
|
+
Handle authentication errors:
|
|
1155
|
+
|
|
1156
|
+
```python
|
|
1157
|
+
from py_directus import Directus
|
|
1158
|
+
|
|
1159
|
+
async def main():
|
|
1160
|
+
try:
|
|
1161
|
+
directus = await Directus(
|
|
1162
|
+
url="https://your-directus-instance.com",
|
|
1163
|
+
email="user@example.com",
|
|
1164
|
+
password="wrong-password"
|
|
1165
|
+
)
|
|
1166
|
+
except Exception as e:
|
|
1167
|
+
print(f"Authentication failed: {e}")
|
|
1168
|
+
|
|
1169
|
+
import asyncio
|
|
1170
|
+
asyncio.run(main())
|
|
1171
|
+
```
|
|
1172
|
+
|
|
1173
|
+
## Request Metadata
|
|
1174
|
+
|
|
1175
|
+
### Access Response Metadata
|
|
1176
|
+
|
|
1177
|
+
```python
|
|
1178
|
+
from py_directus import Directus
|
|
1179
|
+
|
|
1180
|
+
async def main():
|
|
1181
|
+
directus = await Directus(
|
|
1182
|
+
url="https://your-directus-instance.com",
|
|
1183
|
+
token="your-token"
|
|
1184
|
+
)
|
|
1185
|
+
|
|
1186
|
+
response = await directus.collection("articles").read()
|
|
1187
|
+
|
|
1188
|
+
# Access items
|
|
1189
|
+
articles = response.items
|
|
1190
|
+
|
|
1191
|
+
# Access single item (when reading by ID)
|
|
1192
|
+
# article = response.item
|
|
1193
|
+
|
|
1194
|
+
# Check if request was successful
|
|
1195
|
+
print(f"Total items: {len(articles)}")
|
|
1196
|
+
|
|
1197
|
+
import asyncio
|
|
1198
|
+
asyncio.run(main())
|
|
1199
|
+
```
|
|
1200
|
+
|
|
1201
|
+
## Complete Example
|
|
1202
|
+
|
|
1203
|
+
```python
|
|
1204
|
+
import os
|
|
1205
|
+
import asyncio
|
|
1206
|
+
from py_directus import Directus, F
|
|
1207
|
+
|
|
1208
|
+
async def main():
|
|
1209
|
+
# Initialize client
|
|
1210
|
+
directus = await Directus(
|
|
1211
|
+
url=os.getenv("DIRECTUS_URL"),
|
|
1212
|
+
token=os.getenv("DIRECTUS_TOKEN")
|
|
1213
|
+
)
|
|
1214
|
+
|
|
1215
|
+
# Create a new article
|
|
1216
|
+
new_article = {
|
|
1217
|
+
"title": "Getting Started with Directus",
|
|
1218
|
+
"content": "Directus is a powerful headless CMS...",
|
|
1219
|
+
"status": "draft",
|
|
1220
|
+
"author": "author-uuid"
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
create_response = await directus.collection("articles").create(new_article)
|
|
1224
|
+
article_id = create_response.item["id"]
|
|
1225
|
+
print(f"Created article: {article_id}")
|
|
1226
|
+
|
|
1227
|
+
# Read articles with filters
|
|
1228
|
+
read_response = await (
|
|
1229
|
+
directus.collection("articles")
|
|
1230
|
+
.fields("id", "title", "status", "author.name")
|
|
1231
|
+
.filter(status="published")
|
|
1232
|
+
.filter(views__gte=100)
|
|
1233
|
+
.sort("-publish_date")
|
|
1234
|
+
.limit(10)
|
|
1235
|
+
.read()
|
|
1236
|
+
)
|
|
1237
|
+
|
|
1238
|
+
articles = read_response.items
|
|
1239
|
+
print(f"Found {len(articles)} published articles")
|
|
1240
|
+
|
|
1241
|
+
# Update the article
|
|
1242
|
+
update_data = {"status": "published"}
|
|
1243
|
+
await directus.collection("articles").update(article_id, update_data)
|
|
1244
|
+
print(f"Published article: {article_id}")
|
|
1245
|
+
|
|
1246
|
+
# Get statistics
|
|
1247
|
+
stats_response = await (
|
|
1248
|
+
directus.collection("articles")
|
|
1249
|
+
.aggregate(count="id")
|
|
1250
|
+
.aggregate(sum="views")
|
|
1251
|
+
.aggregate(avg="views")
|
|
1252
|
+
.groupby("status")
|
|
1253
|
+
.read()
|
|
1254
|
+
)
|
|
1255
|
+
|
|
1256
|
+
for stat in stats_response.items:
|
|
1257
|
+
print(f"Status: {stat['status']}")
|
|
1258
|
+
print(f"Count: {stat['count']['id']}")
|
|
1259
|
+
print(f"Total views: {stat['sum']['views']}")
|
|
1260
|
+
print(f"Avg views: {stat['avg']['views']}")
|
|
1261
|
+
|
|
1262
|
+
# Clean up - delete the article
|
|
1263
|
+
await directus.collection("articles").delete(article_id)
|
|
1264
|
+
print(f"Deleted article: {article_id}")
|
|
1265
|
+
|
|
1266
|
+
if __name__ == "__main__":
|
|
1267
|
+
asyncio.run(main())
|
|
1268
|
+
```
|
|
1269
|
+
|
|
1270
|
+
## Useful Links
|
|
1271
|
+
|
|
1272
|
+
- Documentation: https://panos-stavrianos.github.io/py-directus/
|
|
1273
|
+
- GitHub Repository: https://github.com/panos-stavrianos/py-directus
|
|
1274
|
+
- PyPI Package: https://pypi.org/project/py-directus/
|
|
1275
|
+
- Directus Official Docs: https://docs.directus.io/
|
|
1276
|
+
- Directus REST API Reference: https://docs.directus.io/reference/introduction
|