Historical Snapshot Cookbook¶
Use this recipe when a report must show one consistent version of the data. Replace Project and its fields with managers from your application.
Python report¶
from datetime import UTC, datetime
from general_manager.api import as_of, current_as_of_date
from myapp.managers import Project
snapshot = datetime(2022, 1, 1, tzinfo=UTC)
with as_of(snapshot) as active_snapshot:
rows = [
{
"id": project.id,
"name": project.name,
"owner": project.owner.name,
}
for project in Project.filter(status="active")
]
assert current_as_of_date() == active_snapshot
print(rows)
The list, each manager attribute, and the nested owner read use the same historical instant. A cached calculation or GraphQL property reached by those reads is namespaced by that instant as well.
Equivalent GraphQL request¶
query HistoricalProjects($date: DateTime!) @asOf(date: $date) {
projectList(filter: {status: "active"}) {
items {
id
name
owner { id name }
}
}
}
{"date": "2022-01-01T00:00:00Z"}
The directive applies to the complete selected operation, not only the projectList field. A literal is also valid:
query HistoricalProjects @asOf(date: "2022-01-01T00:00:00Z") {
projectList { items { id name } }
}
Guard against mixed snapshots¶
from general_manager.api import (
HistoricalContextConflictError,
HistoricalMutationError,
as_of,
)
with as_of("2022-01-01"):
try:
Project(id=42, search_date="2023-01-01")
except HistoricalContextConflictError:
pass
try:
Project.create(name="not allowed", ignore_permission=True)
except HistoricalMutationError:
pass
Use the how-to for migration and error handling guidance, and the API reference for the exact signatures and GraphQL error codes.