angee.base.refs
Generic record references backed by Django contenttypes.
Also the owner of the record-target-across-MTI policy: a polymorphic edge and a REBAC grant see a multi-table-inheritance row from different sides. :func:canonical_record_model and :func:canonical_record_target own the write identity; :func:ancestor_object_refs owns the read/grant fan-out.
Placement invariant. A polymorphic edge that keys on :func:canonical_record_target — storage.FileAttachment, tags.TagAssignment, messaging.ThreadAttachment, knowledge.RecordBinding, and every reverse GenericRelation onto such an edge (messaging.ThreadedModelMixin.thread_attachments, a future tags relation on Party) — must be declared on, and any mixin owning it composed onto, the same topmost REBAC-typed MTI ancestor the canonical write keys on. A reverse GenericRelation filters at its declaring model's own content type, so composing the mixin on a child while its canonical ancestor does not splits the write content type from the collect content type and orphans edge rows on delete.
RecordRef
@dataclass(frozen=True, slots=True)
class RecordRef()Frozen public identity for a model row reached through a generic pointer.
record_ref_for
def record_ref_for(instance: models.Model) -> RecordRefReturn the stable public reference for instance.
CanonicalRecordTarget
class CanonicalRecordTarget(NamedTuple)The content type and id a polymorphic edge must store for a target row.
canonical_record_target
def canonical_record_target(obj: models.Model) -> CanonicalRecordTargetReturn the content type and id a polymorphic edge must store for obj.
The write rule for a generic foreign key across multi-table inheritance: resolve obj to its concrete model first (unwrapping any proxy), then canonicalize to the topmost concrete MTI ancestor that declares a rebac_resource_type — a parties.Person row canonicalizes to its parties.Party ancestor — so a child and its parent share one edge set instead of splitting it across their two content types. Resolving the proxy first means an untyped proxy over a typed concrete row keys on the typed concrete ancestor, never the proxy's own content type: a proxy is a presentation of its concrete row, not a distinct target (this replaces the earlier "keep the proxy's own content type" behavior). A row with no REBAC-typed ancestor keys on its concrete content type. MTI shares one primary key down the pk-link chain, so obj.pk addresses the row at whichever ancestor owns the edge; :func:ancestor_object_refs is the dual that reads every level back.
ancestor_object_refs
def ancestor_object_refs(obj: models.Model) -> tuple[ObjectRef, ...]Return every REBAC identity obj IS-A, nearest identity first.
The read/grant fan-out dual of :func:canonical_record_target: obj's own identity first (raises :class:TypeError if its model declares no rebac_resource_type), then each REBAC-registered concrete MTI ancestor it shares a primary key with (parties.Person IS-A parties.Party). Every identity shares obj's REBAC id, so a grant or read on any ancestor type reaches the same row — the reason a foreign key typed to a parent still scopes the child in. Returned eagerly as a tuple, so the fail-fast fires at the call rather than on first iteration.
canonical_record_model
def canonical_record_model(model: type[models.Model]) -> type[models.Model]Return the topmost concrete MTI ancestor of model with a REBAC type.
This is the model-class projection of :func:canonical_record_target, for callers such as resource metadata that need the canonical label without an instance or a contenttypes query. Proxies unwrap first; untyped rows fall back to their concrete model.
RecordRefMixin
class RecordRefMixin(models.Model)Project a contenttypes-backed row reference from model-owned fields.
record_ref_field_prefix
Reference field prefix; target maps to content_type/object_id.
Meta
class Meta()Django model options for record-ref-only abstract inheritance.
record_ref
@property
def record_ref() -> RecordRefReturn this row's referenced record identity without loading the target.
record_model_label
@property
def record_model_label() -> strReturn the referenced record's app_label.ModelName label.
record_public_id
@property
def record_public_id() -> strReturn the referenced record's stable public id.