Package: py-directus
py-directusDisclaimer: Under developmentDocumentationherepy-directus is a Python wrapper for asynchronous interaction with the Directus headless CMS API. It provides a convenient and
easy-to-use interface for performing CRUD operations, querying data, and managing resources in Directus.FeaturesAsynchronousLogin and authentication handlingReading and writing data from Directus collectionsFiltering, sorting, and searching dataAggregating data using aggregation operatorsCreating, updating, and deleting items in Directus collectionsHandling multiple users in the same sessionDependencies:Pydantic: This library leverages Pydantic for data validation and parsing. Pydantic is a powerful tool in Python for ensuring data integrity and handling data validation with ease.HTTPX: The library utilizes HTTPX, a fully featured HTTP client for Python 3, which provides sync and async APIs, and support for both HTTP/1.1 and HTTP/2.Directus API:
This library interacts with theDirectus API.To make the most of this library, it is highly recommended to familiarize yourself with the Directus API documentation. Understanding the API's capabilities and endpoints will help you effectively utilize this library for seamless integration with Directus.InstallationYou can install the library directly frompypiusing pip:$pipinstallpy-directusFastAPI support requires additional dependencies installation.
You can install them along others like this:$pipinstallpy-directus[FastAPI]Authentication and Session HandlingLoginCreate a Directus instance using email and passwordfrompy_directusimportDirectusdirectus=awaitDirectus("https://example.com",email="user@example.com",password="secret")Alternatively create a Directus instance using the static tokenfrompy_directusimportDirectusdirectus=awaitDirectus("https://example.com",token="static_token")Another way is to use thewithstatement to automatically logout when the session endsasyncwithDirectus(url,email,password)asdirectus:# Manually loginawaitdirectus.login()# Manually start cacheawaitdirectus.start_cache()# do stuff# ORasyncwithawaitDirectus(url,email,password)asdirectus:# do stuffRefresh TokenIf you want to refresh the token you can use therefreshmethodawaitdirectus.refresh()LogoutLogout from Directusawaitdirectus.logout()Multiple Users in the Same SessionYou can use multiple users in the same session by creating a new Directus instance by passing the client objectconnection=httpx.AsyncClient()directus1=awaitDirectus(url,token=token,connection=connection)directus2=awaitDirectus(url,email=email,password=password,connection=connection)CollectionsThere are two ways to set a collection, either by passing the collection name as a string
or by passing the collection as a Pydantic model.Using thecollectionmethod you can pass the collection name as a stringdirectus.collection("directus_users")Or you can pass the collection as aPydanticmodelfromtypingimportOptionalfrompydanticimportConfigDictfrompy_directus.modelsimportDirectusModelclassUser(DirectusModel):id:Optional[str]first_name:Optional[str]last_name:Optional[str]avatar:Optional[str]description:Optional[str]email:Optional[str]role:Optional[str]|Optional[Role]status:Optional[str]title:Optional[str]token:Optional[str]model_config=ConfigDict(collection="directus_users")directus.collection(User)Don't forget to set thecollectionattribute in themodel_configattributeIf you go with the second option, you will get the responses asPydanticmodels (auto parsing)Thecollectionmethod returns aDirectusRequestobject which is used to perform READ, CREATE,
UPDATE and DELETE operationsReading DataWhen you have theDirectusRequestobject you can use thereadmethod to get the data.
This will return aDirectusResponseobject which contains the data.Imporatnt note: Thereadmethod must be awaitedawaitdirectus.collection("directus_users").read()FilteringFor an easy equality filter you can pass the field name and the valueawaitdirectus.collection("directus_users").filter(first_name="John").read()To add multiple equality filters you can chain thefiltermethodawaitdirectus.collection("directus_users").filter(first_name="John").filter(last_name="Doe").read()Using it like this you chain the filters withANDoperatorF objectsTo define complex logic in filters, use theFobjectfrompy_directusimportFawaitdirectus.collection("directus_users").filter((F(first_name="John")|F(first_name="Jane"))&F(last_name="Doe")).read()Important note: TheFobject does not support negationSortingYou can sort the data by passing the field name to thesortmethodawaitdirectus.collection("directus_users").sort("first_name",asc=True).read()To add multiple sorting fields you can chain thesortmethodawaitdirectus.collection("directus_users").sort("first_name",asc=True).sort("last_name",asc=False).read()LimitingYou can limit the data by passing the limit to thelimitmethodawaitdirectus.collection("directus_users").limit(10).read()AggregationAggregate the number of records in the queryawaitdirectus.collection("directus_users").aggregate().read()# ORawaitdirectus.collection("directus_users").aggregate(count="*").read()To add multiple aggregates you can chain theaggregatemethodawaitdirectus.collection("products").aggregate(countDistinct="id").aggregate(sum="price").read()Agg objectsYou can aggregate the data by defining the needed aggregation with theAggclass and passing it to theaggregatemethodfrompy_directus.aggregatorimportAggagg_obj=Agg(operator=AggregationOperators.Count)awaitdirectus.collection("directus_users").aggregate(agg_obj).read()In case you need only certain fieldsfrompy_directus.aggregatorimportAggamount_agg=Agg(operator=AggregationOperators.Sum,fields="amount")awaitdirectus.collection("transactions").aggregate(amount_agg).read()The available aggregation operators are:CountCountDistinctCountAll (Only in GraphQL)SumSumDistinctAverageAverageDistinctMinimumMaximumGroupingYou can group the data by passing the field names to thegroup_bymethodawaitdirectus.collection("directus_users").group_by("first_name","last_name").read()SearchingYou can search the data by passing the search term to thesearchmethodawaitdirectus.collection("directus_users").search("John").read()Selecting FieldsYou can select the fields you want to get by passing the field names to thefieldsmethodawaitdirectus.collection("directus_users").fields("first_name","last_name").read()Getting the Count MetadataYou can get the count of the data (total count and filtered count) callinginclude_countawaitdirectus.collection("directus_users").include_count().read()CRUDRetrieving itemsAfter you callread()you get aDirectusResponseobject which contains the data.itemfor single itemitemsfor multiple itemsGetting the data as a dictionary or a list of dictionariesresponse=awaitdirectus.collection("directus_users").read()print(response.item["first_name"])print(response.items)If you provide thecollectionmethod aPydanticmodel you will get the data as aPydanticobject or a list ofPydanticobjectsresponse=awaitdirectus.collection(User).read()print(response.item.first_name)print(response.items)Converting to Models (pydantic) or to DictionaryApart from the auto parsing, you can manually convert the data to aPydanticmodel instance or to a dictionary using:item_as(User)oritems_as(User)item_as_dict()oritems_as_dict()response=awaitdirectus.collection("directus_users").read()print(response.item_as(User))response=awaitdirectus.collection(User).read()print(response.item_as_dict())Creating ItemsThe library does not supportPydanticmodels for creation, you have to pass a dictionarycreate(items: dict|List[dict])awaitdirectus.collection("directus_users").create({"first_name":"John","last_name":"Doe"})# ORawaitdirectus.collection("directus_users").create([{"first_name":"John","last_name":"Doe"},{"first_name":"Jane","last_name":"Doe"}])Updating ItemsThe library do not supportPydanticmodels for updating, you have to pass a dictionaryupdate(ids: str|int, items: dict)update(ids: List[str|int], items: List[dict])awaitdirectus.collection("directus_users").update(1,{"first_name":"Red","last_name":"John"})# ORawaitdirectus.collection("directus_users").update([1,2],[{"first_name":"Jean-Luc"},{"first_name":"Jane","last_name":"Doe"}])Deleting Itemsdelete(ids: str|int|List[str|int])awaitdirectus.collection("directus_users").delete(1)# ORawaitdirectus.collection("directus_users").delete([1,2])SupportingPydanticmodels forcreate/update/deleteitem operations is shortly coming.ExamplesExamples are not included with thepypipackage, so you will have to download them separately and execute in a virtual environment.Run individual examples as such:python-mexamples.<example_file_name>TestsRun tests as such:# All unit testspython-munittestdiscover-stests/unit# All integration testspython-munittestdiscover-stests/integration