1+ import json
12from circuits .api .serializers import CircuitSerializer , ProviderSerializer
23from dcim .api .serializers import (
34 LocationSerializer ,
78from rest_framework import serializers
89
910from cesnet_service_path_plugin .models .segment import Segment
11+ from cesnet_service_path_plugin .utils import export_segment_paths_as_geojson
1012
1113
1214class SegmentSerializer (NetBoxModelSerializer ):
13- url = serializers . HyperlinkedIdentityField (
14- view_name = "plugins-api:cesnet_service_path_plugin-api:segment-detail"
15- )
15+ """Default serializer Segment - excludes heavy geometry fields"""
16+
17+ url = serializers . HyperlinkedIdentityField ( view_name = "plugins-api:cesnet_service_path_plugin-api:segment-detail" )
1618 provider = ProviderSerializer (required = True , nested = True )
1719 site_a = SiteSerializer (required = True , nested = True )
1820 location_a = LocationSerializer (required = True , nested = True )
1921 site_b = SiteSerializer (required = True , nested = True )
2022 location_b = LocationSerializer (required = True , nested = True )
2123 circuits = CircuitSerializer (required = False , many = True , nested = True )
2224
25+ # Only include lightweight path info
26+ has_path_data = serializers .SerializerMethodField (read_only = True )
27+
2328 class Meta :
2429 model = Segment
2530 fields = (
@@ -40,6 +45,11 @@ class Meta:
4045 "site_b" ,
4146 "location_b" ,
4247 "circuits" ,
48+ # Only basic path info, no heavy geometry
49+ "path_length_km" ,
50+ "path_source_format" ,
51+ "path_notes" ,
52+ "has_path_data" ,
4353 "tags" ,
4454 )
4555 brief_fields = (
@@ -48,9 +58,165 @@ class Meta:
4858 "display" ,
4959 "name" ,
5060 "status" ,
61+ "has_path_data" ,
5162 "tags" ,
5263 )
5364
65+ def get_has_path_data (self , obj ):
66+ return obj .has_path_data ()
67+
68+
69+ class SegmentListSerializer (NetBoxModelSerializer ):
70+ """Lightweight serializer for list views - excludes heavy geometry fields"""
71+
72+ url = serializers .HyperlinkedIdentityField (view_name = "plugins-api:cesnet_service_path_plugin-api:segment-detail" )
73+ provider = ProviderSerializer (required = True , nested = True )
74+ site_a = SiteSerializer (required = True , nested = True )
75+ location_a = LocationSerializer (required = True , nested = True )
76+ site_b = SiteSerializer (required = True , nested = True )
77+ location_b = LocationSerializer (required = True , nested = True )
78+ circuits = CircuitSerializer (required = False , many = True , nested = True )
79+
80+ # Only include lightweight path info
81+ has_path_data = serializers .SerializerMethodField (read_only = True )
82+
83+ class Meta :
84+ model = Segment
85+ fields = (
86+ "id" ,
87+ "url" ,
88+ "display" ,
89+ "name" ,
90+ "status" ,
91+ "network_label" ,
92+ "install_date" ,
93+ "termination_date" ,
94+ "provider" ,
95+ "provider_segment_id" ,
96+ "provider_segment_name" ,
97+ "provider_segment_contract" ,
98+ "site_a" ,
99+ "location_a" ,
100+ "site_b" ,
101+ "location_b" ,
102+ "circuits" ,
103+ # Only basic path info, no heavy geometry
104+ "path_length_km" ,
105+ "path_source_format" ,
106+ "path_notes" ,
107+ "has_path_data" ,
108+ "tags" ,
109+ )
110+ brief_fields = (
111+ "id" ,
112+ "url" ,
113+ "display" ,
114+ "name" ,
115+ "status" ,
116+ "has_path_data" ,
117+ "tags" ,
118+ )
119+
120+ def get_has_path_data (self , obj ):
121+ return obj .has_path_data ()
122+
123+
124+ class SegmentDetailSerializer (NetBoxModelSerializer ):
125+ """Full serializer with all geometry data for detail views"""
126+
127+ # This is your existing SegmentSerializer - just rename it
128+ url = serializers .HyperlinkedIdentityField (view_name = "plugins-api:cesnet_service_path_plugin-api:segment-detail" )
129+ provider = ProviderSerializer (required = True , nested = True )
130+ site_a = SiteSerializer (required = True , nested = True )
131+ location_a = LocationSerializer (required = True , nested = True )
132+ site_b = SiteSerializer (required = True , nested = True )
133+ location_b = LocationSerializer (required = True , nested = True )
134+ circuits = CircuitSerializer (required = False , many = True , nested = True )
135+
136+ # All the heavy geometry fields
137+ path_geometry_geojson = serializers .SerializerMethodField (read_only = True )
138+ path_coordinates = serializers .SerializerMethodField (read_only = True )
139+ path_bounds = serializers .SerializerMethodField (read_only = True )
140+ has_path_data = serializers .SerializerMethodField (read_only = True )
141+
142+ class Meta :
143+ model = Segment
144+ fields = (
145+ "id" ,
146+ "url" ,
147+ "display" ,
148+ "name" ,
149+ "status" ,
150+ "network_label" ,
151+ "install_date" ,
152+ "termination_date" ,
153+ "provider" ,
154+ "provider_segment_id" ,
155+ "provider_segment_name" ,
156+ "provider_segment_contract" ,
157+ "site_a" ,
158+ "location_a" ,
159+ "site_b" ,
160+ "location_b" ,
161+ "circuits" ,
162+ # All path geometry fields
163+ "path_geometry_geojson" ,
164+ "path_coordinates" ,
165+ "path_bounds" ,
166+ "path_length_km" ,
167+ "path_source_format" ,
168+ "path_notes" ,
169+ "has_path_data" ,
170+ "tags" ,
171+ )
172+ brief_fields = (
173+ "id" ,
174+ "url" ,
175+ "display" ,
176+ "name" ,
177+ "status" ,
178+ "has_path_data" ,
179+ "tags" ,
180+ )
181+
182+ def get_path_geometry_geojson (self , obj ):
183+ """
184+ Return path geometry as GeoJSON Feature
185+ """
186+ if not obj .has_path_data ():
187+ return None
188+
189+ try :
190+
191+ geojson_str = export_segment_paths_as_geojson ([obj ])
192+ geojson_data = json .loads (geojson_str )
193+
194+ # Return just the first (and only) feature, not the entire FeatureCollection
195+ if geojson_data .get ("features" ):
196+ return geojson_data ["features" ][0 ]
197+ return None
198+ except Exception :
199+ # Fallback to basic GeoJSON if utility function fails
200+ return obj .get_path_geojson ()
201+
202+ def get_path_coordinates (self , obj ):
203+ """
204+ Return path coordinates as list of LineString coordinate arrays
205+ """
206+ return obj .get_path_coordinates ()
207+
208+ def get_path_bounds (self , obj ):
209+ """
210+ Return bounding box of the path geometry [xmin, ymin, xmax, ymax]
211+ """
212+ return obj .get_path_bounds ()
213+
214+ def get_has_path_data (self , obj ):
215+ """
216+ Return boolean indicating if segment has path data
217+ """
218+ return obj .has_path_data ()
219+
54220 def validate (self , data ):
55221 # Enforce model validation
56222 super ().validate (data )
0 commit comments