1010from cesnet_service_path_plugin .models .segment import Segment
1111from cesnet_service_path_plugin .utils import export_segment_paths_as_geojson
1212
13+ from cesnet_service_path_plugin .utils import process_path_data , determine_file_format_from_extension
14+ from django .core .exceptions import ValidationError as DjangoValidationError
15+
1316
1417class SegmentSerializer (NetBoxModelSerializer ):
15- """Default serializer Segment - excludes heavy geometry fields """
18+ """Default serializer Segment - now with file upload support """
1619
1720 url = serializers .HyperlinkedIdentityField (view_name = "plugins-api:cesnet_service_path_plugin-api:segment-detail" )
1821 provider = ProviderSerializer (required = True , nested = True )
@@ -22,60 +25,12 @@ class SegmentSerializer(NetBoxModelSerializer):
2225 location_b = LocationSerializer (required = True , nested = True )
2326 circuits = CircuitSerializer (required = False , many = True , nested = True )
2427
25- # Only include lightweight path info
26- has_path_data = serializers .SerializerMethodField (read_only = True )
27-
28- class Meta :
29- model = Segment
30- fields = (
31- "id" ,
32- "url" ,
33- "display" ,
34- "name" ,
35- "status" ,
36- "network_label" ,
37- "install_date" ,
38- "termination_date" ,
39- "provider" ,
40- "provider_segment_id" ,
41- "provider_segment_name" ,
42- "provider_segment_contract" ,
43- "site_a" ,
44- "location_a" ,
45- "site_b" ,
46- "location_b" ,
47- "circuits" ,
48- # Only basic path info, no heavy geometry
49- "path_length_km" ,
50- "path_source_format" ,
51- "path_notes" ,
52- "has_path_data" ,
53- "tags" ,
54- )
55- brief_fields = (
56- "id" ,
57- "url" ,
58- "display" ,
59- "name" ,
60- "status" ,
61- "has_path_data" ,
62- "tags" ,
63- )
64-
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 )
28+ # Add file upload field
29+ path_file = serializers .FileField (
30+ required = False ,
31+ write_only = True , # Only for input, not included in output
32+ help_text = "Upload a file containing the path geometry. Supported formats: GeoJSON (.geojson, .json), KML (.kml), KMZ (.kmz)" ,
33+ )
7934
8035 # Only include lightweight path info
8136 has_path_data = serializers .SerializerMethodField (read_only = True )
@@ -105,6 +60,7 @@ class Meta:
10560 "path_source_format" ,
10661 "path_notes" ,
10762 "has_path_data" ,
63+ "path_file" , # Add the file field
10864 "tags" ,
10965 )
11066 brief_fields = (
@@ -120,6 +76,64 @@ class Meta:
12076 def get_has_path_data (self , obj ):
12177 return obj .has_path_data ()
12278
79+ def update (self , instance , validated_data ):
80+ """Handle file upload during update"""
81+ path_file = validated_data .pop ("path_file" , None )
82+
83+ # Update other fields first
84+ instance = super ().update (instance , validated_data )
85+
86+ # Process uploaded file if provided
87+ if path_file :
88+ try :
89+ # Process the uploaded file using existing utility functions
90+ file_format = determine_file_format_from_extension (path_file .name )
91+ path_geometry = process_path_data (path_file , file_format )
92+
93+ # Update instance with processed geometry
94+ instance .path_geometry = path_geometry
95+ instance .path_source_format = file_format
96+ # path_length_km will be auto-calculated in the model's save method
97+ instance .save ()
98+
99+ except DjangoValidationError as e :
100+ raise serializers .ValidationError (f"Path file error: { str (e )} " )
101+ except Exception as e :
102+ raise serializers .ValidationError (f"Error processing file '{ path_file .name } ': { str (e )} " )
103+
104+ return instance
105+
106+ def create (self , validated_data ):
107+ """Handle file upload during creation"""
108+ path_file = validated_data .pop ("path_file" , None )
109+
110+ # Create instance without path data first
111+ instance = super ().create (validated_data )
112+
113+ # Process uploaded file if provided
114+ if path_file :
115+ try :
116+ # Process the uploaded file using existing utility functions
117+ file_format = determine_file_format_from_extension (path_file .name )
118+ path_geometry = process_path_data (path_file , file_format )
119+
120+ # Update instance with processed geometry
121+ instance .path_geometry = path_geometry
122+ instance .path_source_format = file_format
123+ # path_length_km will be auto-calculated in the model's save method
124+ instance .save ()
125+
126+ except DjangoValidationError as e :
127+ # Clean up created instance if path processing fails
128+ instance .delete ()
129+ raise serializers .ValidationError (f"Path file error: { str (e )} " )
130+ except Exception as e :
131+ # Clean up created instance if path processing fails
132+ instance .delete ()
133+ raise serializers .ValidationError (f"Error processing file '{ path_file .name } ': { str (e )} " )
134+
135+ return instance
136+
123137
124138class SegmentDetailSerializer (NetBoxModelSerializer ):
125139 """Full serializer with all geometry data for detail views"""
0 commit comments