# To multiple records

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

Relationships that point to multiple records are displayed in the frontend in the "Related Data" and "Explorer" Tab.

![Explorer Tab](/files/ncfg8xnvhHb98lrK7IZ1)

### One-to-Many relations

In a one-to-many relationship, one record from a Collection is attached to multiple records of another Collection.

Think about countries and towns: a country has multiple towns, and each town belongs to a country.

```python
# Link 'countries' to 'towns'
agent.customize_collection('countries').add_one_to_many_relation(
    name='myTowns',
    foreign_collections='towns',
    origin_key='country_id',
    origin_key_target='id', # Optional (uses primary key of countries by default)
)
```

### Many-to-Many relations

In a many-to-many relation, 3 Collections are used instead of 2 to build the relation.

This allows multiple records from one Collection to be attached to multiple records from another Collection.

For instance, on a movie recommendation website, each user can rate many movies, and each movie can be rated by many users. The 3 Collections that are used are `users` (the "origin" Collection), `ratings` (the "through" Collection), and `movies` (the "foreign" Collection).

```python
# Create one side of the relation ..
agent.customize_collection('users').add_many_to_many_relation(
    name='ratedMovies',
    foreign_collection='Movie',
    through_collection='Rating'
    origin_key='user_id',
    origin_key_target='id', # Optional (uses primary key of User by default)
    foreign_key='movie_id',
    foreign_key_target='id' # Optional (uses primary key of Movie by default)
)
```

### External relations

External relations allow to define Collections which will only be available through the "Related Data" section or a given model.

{% hint style="warning" %}
Note that external relations do not support pagination.
{% endhint %}

```python
from forestadmin.datasource_toolkit.context.collection_context import (
    CollectionCustomizationContext
)
from forestadmin.datasource_toolkit.interfaces.records import RecordsDataAlias

STATES = [
    {"code": "AK", "name": "Alaska", "zip": [99501, 99950], "closeTo": []},
    {
        "code": "AL",
        "name": "Alabama",
        "zip": [35004, 36925],
        "closeTo": ["TE", "MI", "GE"],
    },
    {
        "code": "AR",
        "name": "Arkansas",
        "zip": [71601, 72959],
        "closeTo": ["OK", "TX", "LO"],
    },
    {
        "code": "AZ",
        "name": "Arizona",
        "zip": [85001, 86556],
        "closeTo": ["NM", "CO", "NE"],
    },
    {
        "code": "CA",
        "name": "California",
        "zip": [90001, 96162],
        "closeTo": ["OR", "NE"]
    },
    # ....
]

async def near_states_list_records(
    record: RecordsDataAlias, context: CollectionCustomizationContext
) -> Any:
    ret = []
    if record["country"] == "USA":
        zip_code = record["zipCode"]
        for state in STATES:
            if not (state["zip"][0] < zip_code and zip_code < state["zip"][1]):
                continue
            ret.extend(filter(lambda s: s["code"] in state["closeTo"], STATES))

    return ret

# Create one side of the relation ..
agent.customize_collection('address').add_external_relation(
    "nearStates",
    {
        # Define schema of the records in the relation.
        "schema": { "code": "Sting", "name": "String" },

        # Which fields are needed from the parent record to run the handler?
        # Dependencies are optional: by default only the primary key of address
        # would be provided.
        "dependencies": ['country', 'zipCode'],

        # Compute list of records from the parent record
        "list_records": near_states_list_records
    }
)
```


---

# 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/agent-customization/relationships/multiple-records.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.
