# Translation strategy

{% hint style="success" %}
This is the official documentation of the `forestadmin-agent-django` and `forestadmin-agent-flask` Python agents.
{% endhint %}

### Steps

Creating a custom data source will require you to work on the 3 following steps:

1. Declare the structure of the data
2. Declare the API capabilities
3. Code a translation layer

### Minimal example

```python
from typings import Optional

from forestadmin.agent_toolkit.utils.context import User
from forestadmin.datasource_toolkit.collections import Collection
from forestadmin.datasource_toolkit.datasources import Datasource
from forestadmin.datasource_toolkit.interfaces.query.aggregation import AggregateResult, Aggregation
from forestadmin.datasource_toolkit.interfaces.query.filter.paginated import PaginatedFilter
from forestadmin.datasource_toolkit.interfaces.query.filter.unpaginated import Filter
from forestadmin.datasource_toolkit.interfaces.query.projections import Projection
from forestadmin.datasource_toolkit.interfaces.records import RecordsDataAlias

import requests  # client for the target API

# The real work is in writing this module
# Expect a full featured query translation module to be over 1000 LOCs
from .forest_query_translation import QueryGenerator

# Minimal implementation of a readonly data source
class MyCollection(Collection):
    def __init__(self, datasource):
        # Set name of the collection once imported
        super().__init__("MyCollection", datasource)

        # structure
        self.add_field("id", {
            "type": "Column",
            "column_type": "Number",
            "is_primary_key": True,
            "is_read_only": True,  # field is readonly
            # As we are using the query translation strategy => define capabilities
            "filter_operators": set(), # field is not filterable
            "is_sortable": False, # field is not sortable
        })

        self.add_field("title", {
            "type": "Column",
            "column_type": "String",
            "is_read_only": True,
            "filter_operators": set(),
            "is_sortable": False,
        })

    async def list(
        self,
        caller: User,
        filter_: PaginatedFilter,
        projection: Projection
    ) -> List[RecordsDataAlias]:
        params = QueryGenerator.generate_list_query_string(filter_, projection)
        response = requests.get('https://my-api/my-collection', params)

        return response.json()["items"]

    async def aggregate(
        self,
        caller: User,
        filter_: Filter,
        aggregation: Aggregation,
        limit: Optional[int]
    ) -> List[AggregateResult]:
        params = QueryGenerator.generate_aggregate_query_string(
            filter_,
            aggregation,
            limit
        )
        response = requests.get('https://my-api/my-collection', params)

        return response.json()["items"]

class MyDatasource(Datasource):
    def __init__(self):
        super().__init__()
        self.add_collection(MyCollection(self))

```

```python
from custom_datasources.my_datasource import MyDatasource

agent.add_datasource(MyDatasource())
```

### Read more

Implementing a data source using the "query translation" strategy is an advanced concept: you will need to have a deep understanding of Forest Admin internals.

This strategy is a good match when writing data sources for full-featured databases.

Before starting, it is highly advised to read and understand the following sections:

* [Data Model Typing](/developer-guide-agents-python/under-the-hood/data-model/typing.md)
* [Data Model Relationships](/developer-guide-agents-python/under-the-hood/data-model/relationships.md)
* [Query interface](/developer-guide-agents-python/data-sources/getting-started/queries.md)
* [Fields and projections](/developer-guide-agents-python/data-sources/getting-started/queries/fields-projections.md)
* [Filters](/developer-guide-agents-python/data-sources/getting-started/queries/filters.md)
* [Aggregations](/developer-guide-agents-python/data-sources/getting-started/queries/aggregations.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.forestadmin.com/developer-guide-agents-python/data-sources/custom/translation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
