Coverage for backend/django/core/serializer_base.py: 91%
36 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-07-22 05:22 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-07-22 05:22 +0000
1from rest_framework import serializers
2from drf_spectacular.types import OpenApiTypes
3from drf_spectacular.utils import extend_schema_field
5from core.validation import get_current_flowsheet
8@extend_schema_field(OpenApiTypes.INT)
9class StableFlowsheetIdentityField(serializers.Field):
10 """Accept and return public stable identity without persisting a duplicate FK."""
12 def get_attribute(self, instance):
13 """Pass the full state-owned instance to ``to_representation``."""
15 return instance
17 def to_representation(self, value) -> int:
18 """Return stable identity without loading the state once per row."""
20 context = get_current_flowsheet() or {}
21 active_state_id = context.get("flowsheet_state")
22 active_flowsheet_id = context.get("flowsheet")
23 if (
24 active_state_id is not None
25 and active_flowsheet_id is not None
26 and value.flowsheet_state_id == int(active_state_id)
27 ):
28 return int(active_flowsheet_id)
30 return value.flowsheet_state.flowsheet_id
32 def to_internal_value(self, data) -> dict:
33 """Validate a legacy/public flowsheet payload against request context."""
35 try:
36 flowsheet_id = int(data)
37 except (TypeError, ValueError):
38 raise serializers.ValidationError("A valid flowsheet ID is required.")
39 if flowsheet_id < 1: 39 ↛ 40line 39 didn't jump to line 40 because the condition on line 39 was never true
40 raise serializers.ValidationError("A valid flowsheet ID is required.")
42 context = get_current_flowsheet() or {}
43 active_flowsheet_id = context.get("flowsheet")
44 if (
45 active_flowsheet_id is not None
46 and flowsheet_id != int(active_flowsheet_id)
47 ):
48 raise serializers.ValidationError(
49 "Flowsheet must match the active request flowsheet."
50 )
52 # ``source='*'`` merges this mapping into validated data. Returning an
53 # empty mapping deliberately accepts the public identity without adding
54 # a nonexistent stable FK to the model constructor.
55 return {}
58class StateOwnedModelSerializer(serializers.ModelSerializer):
59 """Expose stable flowsheet identity while keeping state IDs internal."""
61 flowsheet = StableFlowsheetIdentityField(source="*", required=False)
63 def get_field_names(self, declared_fields, info):
64 """Replace the database state field with the stable public identifier."""
66 field_names = list(super().get_field_names(declared_fields, info))
67 if "flowsheet_state" in field_names:
68 field_names.remove("flowsheet_state")
69 if "flowsheet" not in field_names:
70 field_names.append("flowsheet")
71 return field_names