Scope and context

This is the official documentation of the forestadmin-agent-django and forestadmin-agent-flask Python agents.

Actions can have 3 different scopes: Single, Bulk, and Global.

The scope of an action defines how it can be triggered and which records it will target.

The context object

The context object is central to writing Actions controllers in Forest Admin.

It is the bridge between all the data that your agent has access to and the action's execution. It is passed to the execute function as the first argument and provides access to the following properties:

  • get_record (or get_records for Bulk and Global Actions)

  • get_record_id (or get_record_ids for Bulk and Global Actions)

  • collection the collection on which the action is declared.

  • filter a filter that can be used to query the collection, and which is based on action scope and the list of selected records.

  • caller an object containing information about the user who is performing the action (including email, username, timezone, team, role …)

  • has_field_changed(field_name) the name of the field who has changed in the UI. See an example of usage

changed_field was deprecated in favor of has_field_changed(field_name) starting from forestadmin-datasource-toolkit==1.0.0-beta14.

Example 1: Getting data from the selected records

We can simply use the getRecord() method to get any column from the selected record or a relation.

from typing import Union
from forestadmin.datasource_toolkit.decorators.action.result_builder import ResultBuilder
from forestadmin.datasource_toolkit.decorators.action.context.single import ActionContextSingle
from forestadmin.datasource_toolkit.interfaces.actions import ActionResult

async def execute(
    context: ActionContextSingle, result_builder: ResultBuilder
) -> Union[None, ActionResult]:
  record = await context.get_record(['name'])
  if record['name'] === 'John':
      print("hi John")
  else
      print("You are not John!")

agent.customize_collection("User").add_action("Call me John in the server logs", {
    "scope": "Single",
    "execute": execute,
})

Example 2: Updating a field of the selected record

For simple queries, use context.collection and context.filter to query the collection.

from typing import Union
from forestadmin.datasource_toolkit.decorators.action.result_builder import ResultBuilder
from forestadmin.datasource_toolkit.decorators.action.context.single import ActionContextSingle
from forestadmin.datasource_toolkit.interfaces.actions import ActionResult

async def execute(
    context: ActionContextSingle, result_builder: ResultBuilder
) -> Union[None, ActionResult]:
    await context.collection.update(context.filter, {"name": "foo"})

agent.customize_collection("User").add_action("Mark as live", {
    "scope": "Single",
    "execute": execute,
})

Example 3: Coding any business logic

Forest Admin does not impose any restriction on the handler: you are free to write the execute handler to fit your use case.

You are free to call external APIs, query your database, or perform any work in action handlers.

from typing import Union
from forestadmin.datasource_toolkit.decorators.action.result_builder import ResultBuilder
from forestadmin.datasource_toolkit.decorators.action.context.single import ActionContextSingle

import requests

async def execute(
    context: ActionContextSingle, result_builder: ResultBuilder
) -> Union[None, ActionResult]:
    res = requests.get("http://my-api.com/mark-as-live")

agent.customize_collection("User").add_action("Mark as live", {
    "scope": "Single",
    "execute": execute,
})

Last updated