This is the official documentation of the forestadmin-agent-django and forestadmin-agent-flask Python agents.
Relationships that point to multiple records are displayed in the frontend in the "Related Data" and "Explorer" Tab.
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.
# 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).
# 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.
Note that external relations do not support pagination.
from forestadmin.datasource_toolkit.context.collection_context import ( CollectionCustomizationContext)from forestadmin.datasource_toolkit.interfaces.records import RecordsDataAliasSTATES = [{"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"]},# ....]asyncdefnear_states_list_records(record: RecordsDataAlias,context: CollectionCustomizationContext) -> Any: ret = []if record["country"]=="USA": zip_code = record["zipCode"]for state in STATES:ifnot (state["zip"][0] < zip_code and zip_code < state["zip"][1]):continue ret.extend(filter(lambdas: 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 })