Subrequests
Background
farmOS.py supports the Subrequests module included with a farmOS server.
Subrequests allows multiple requests to be defined in a "blueprint" and sent to the server in a single POST request. The blueprint can define sequential requests so that the response of one request can be embedded into the body of a later request. See the subrequests blueprint specification for more documentation.
farmOS.py provides some additional features to help use subrequests:
- The default response format is set to
json
by appending a?_format=json
query parameter automatically. JSON is much easier to parse than subrequest's defaulthtml
format, but HTML can be requested by specifyingformat='html'
. - Unless otherwise provided, the
Accept
andContent-Type
headers for each sub-request will be set toapplication/vnd.api+json
for standard JSONAPI requests. - An
endpoint
can be provided instead of the fulluri
for each sub-request. farmOS.py will build the fulluri
from thehostname
already configured with the client. - The sub-request
body
can be provided as an object that farmOS.py will serialize into a JSON object string. - Blueprints are validated using Pydantic models. These models can also be used to build individual requests to include in a blueprint.
Example
An example that creates a new asset followed by a new log that references the asset:
from farmOS import farmOS
from farmOS.subrequests import Action, Subrequest, SubrequestsBlueprint, Format
client = farmOS("http://localhost", scope="farm_manager", version=2)
client.authorize('username', 'password')
plant_type = {
"data": {
"type": "taxonomy_term--plant_type",
"attributes": {
"name": "New plant type"
}
}
}
new_plant_type = Subrequest(action=Action.create, requestId="create-plant-type", endpoint="api/taxonomy_term/plant_type", body=plant_type)
plant = {
"data": {
"type": "asset--plant",
"attributes": {
"name": "My new plant",
"notes": "Created in the first request.",
},
"relationships": {
"plant_type": {
"data": [
{
"type": "taxonomy_term--plant_type",
"id": "{{create-plant-type.body@$.data.id}}"
}
]
}
}
}
}
new_asset = Subrequest(action=Action.create, requestId="create-asset", waitFor=["create-plant-type"], endpoint="api/asset/plant", body=plant)
log = {
"data": {
"type": "log--seeding",
"attributes": {
"name": "Seeding my new plant",
"notes": "Created in the second request.",
},
"relationships": {
"asset": {
"data": [
{
"type": "asset--plant",
"id": "{{create-asset.body@$.data.id}}"
}
]
}
}
}
}
new_log = Subrequest(action=Action.create, requestId="create-log", waitFor=["create-asset"], endpoint="api/log/seeding", body=log)
# Create a blueprint object
blueprint = SubrequestsBlueprint.parse_obj([new_plant_type, new_asset, new_log])
# OR provide a list of Subrequest objects.
blueprint = [new_plant_type, new_asset, new_log]
# Send the blueprint.
response = client.subrequests.send(blueprint, format=Format.json)