Geometry QuerySet Examples¶
These examples map the geometry schema that the SDK exposes through
GeometryAPI and the geometry processing structures in this workspace.
The join paths are taken from the live client code and tests, not from a
simplified diagram.
One detail matters immediately: the checked-in SDK exercises the
SubAssembly to asset-location relation with the Django filter path
asset__..., even though some higher-level schema notes call the field
asset_location. The examples below follow the concrete filter path used
by the backend-facing code in this workspace.
Shell Setup¶
# Geometry and location models used throughout the examples.
from django.db.models import Prefetch
from geometry.models import (
BuildingBlock,
DistributedMass,
LumpedMass,
Material,
ModelDefinition,
SubAssembly,
TubularSection,
)
from locations.models import AssetLocation, ProjectSite
Data Model Overview¶
ModelDefinitionbelongs to a project record; the geometry client resolves it from a project site throughGeometryAPI.get_model_definitions().SubAssemblybelongs to both aModelDefinitionand an asset row, and the SDK filters that relation asasset__projectsite__titleandasset__title.BuildingBlockbelongs toSubAssemblythroughsub_assembly.TubularSectionbelongs toBuildingBlockandMaterial.LumpedMassandDistributedMassare building-block specializations keyed by the same building-block row.
Entity Relationship Diagram¶
erDiagram
ProjectSite {
int id PK
string slug
string title
}
AssetLocation {
int location_id PK
int projectsite_id FK
string title
}
ModelDefinition {
int id PK
int project_id FK
string title
}
SubAssembly {
int id PK
int model_definition_id FK
int asset_id FK
string subassembly_type
}
BuildingBlock {
int id PK
int sub_assembly_id FK
}
Material {
int id PK
string title
}
TubularSection {
int building_block_id PK
int material_id FK
}
LumpedMass {
int building_block_id PK
}
DistributedMass {
int building_block_id PK
}
ProjectSite ||--o{ AssetLocation : projectsite_id
ModelDefinition ||--o{ SubAssembly : model_definition_id
AssetLocation ||--o{ SubAssembly : asset_id
SubAssembly ||--o{ BuildingBlock : sub_assembly_id
BuildingBlock ||--|| TubularSection : building_block_id
BuildingBlock ||--|| LumpedMass : building_block_id
BuildingBlock ||--|| DistributedMass : building_block_id
Material ||--o{ TubularSection : material_id
Query Flow¶
flowchart LR
ProjectSite[ProjectSite]
AssetLocation[AssetLocation]
ModelDefinition[ModelDefinition]
SubAssembly[SubAssembly]
BuildingBlock[BuildingBlock]
TubularSection[TubularSection]
Material[Material]
ProjectSite --> AssetLocation
ProjectSite --> ModelDefinition
AssetLocation --> SubAssembly
ModelDefinition --> SubAssembly
SubAssembly --> BuildingBlock
BuildingBlock --> TubularSection
TubularSection --> Material
Basic Queries¶
# Retrieve every model definition.
ModelDefinition.objects.all()
# Scope model definitions to the Nobelwind project hierarchy.
ModelDefinition.objects.filter(project__projectsite__slug="nobelwind")
# Pull all transition-piece subassemblies for Nobelwind.
SubAssembly.objects.filter(
asset__projectsite__slug="nobelwind",
subassembly_type="TP",
)
# Retrieve building blocks for one subassembly.
BuildingBlock.objects.filter(sub_assembly_id=235)
Deep Joins¶
# Start at the deepest structural level and walk back to the project site.
SubAssembly.objects.filter(
model_definition__project__projectsite__slug="nobelwind"
)
# Match the exact path used by GeometryAPI.get_buildingblocks(projectsite=...).
BuildingBlock.objects.filter(
sub_assembly__asset__projectsite__title="Nobelwind"
)
# Traverse from project site to the material rows referenced by tubular
# sections on the related building blocks.
Material.objects.filter(
tubularsection__building_block__sub_assembly__asset__projectsite__slug="nobelwind"
).distinct()
Related Fetching¶
# Join the owning model definition and asset row when loading subassemblies.
SubAssembly.objects.select_related("model_definition", "asset").filter(
asset__projectsite__slug="nobelwind"
)
# Join all forward relations needed to inspect one tubular section.
TubularSection.objects.select_related(
"building_block",
"building_block__sub_assembly",
"building_block__sub_assembly__asset",
"material",
)
Reverse Relations And Prefetching¶
# Walk from an asset location down to subassemblies, then prefetch the
# related building blocks in the same request cycle.
AssetLocation.objects.filter(projectsite__slug="nobelwind").prefetch_related(
Prefetch("subassembly_set", queryset=SubAssembly.objects.prefetch_related("buildingblock_set"))
)
# This is the project-site level traversal many views eventually need.
ProjectSite.objects.filter(slug="nobelwind").prefetch_related(
"location_set__assetlocation__subassembly_set"
)
Specialized Building-Block Types¶
# Tubular sections carry the material FK.
TubularSection.objects.filter(
building_block__sub_assembly__asset__title="BBA01"
).select_related("material")
# Mass blocks are separate tables keyed by the building-block row.
LumpedMass.objects.filter(
building_block__sub_assembly__asset__title="BBA01"
)
DistributedMass.objects.filter(
building_block__sub_assembly__asset__title="BBA01"
)
SDK Alignment¶
The core SDK forwards these same join paths to the backend.
from owi.metadatabase.geometry.io import GeometryAPI
api = GeometryAPI(token="your-api-token")
# The SDK turns `projectsite="Nobelwind"` into
# `asset__projectsite__title="Nobelwind"` for the subassembly endpoint.
api.get_subassemblies(projectsite="Nobelwind")
# The SDK turns `assetlocation="BBA01"` into `asset__title="BBA01"`.
api.get_subassemblies(assetlocation="BBA01", subassembly_type="TW")
# Building-block filtering uses the deeper `sub_assembly__asset__...` path.
api.get_buildingblocks(projectsite="Nobelwind", assetlocation="BBA01")
When you need the model definition selected exactly the way the SDK does, match its scope first and then filter by title.
# QuerySet equivalent of GeometryAPI.get_modeldefinition_id(...).
ModelDefinition.objects.filter(
project__projectsite__title="Nobelwind",
title="as-built Belwind",
)
Live Route Validation¶
The live dev geometry list route was validated on 2026-03-23.
- Working live route:
/api/v1/geometry/routes/modeldefinitions/ - Observed 404 route:
/api/v1/geometry/routes/modeldefinition/ - Confirmed working list filters:
site,title - Confirmed examples:
site=Belwind,site=Nobelwind,title=as-built Belwind - Confirmed empty-result behavior:
title=does-not-existreturns[] - Observed as ineffective on this list route:
project,id
This aligns with the checked-in SDK implementation: GeometryAPI
requests the plural modeldefinitions route and scopes it with
site=....