endoreg-db 0.6.1__py3-none-any.whl → 0.6.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of endoreg-db might be problematic. Click here for more details.

Files changed (28) hide show
  1. endoreg_db/data/distribution/numeric/data.yaml +1 -1
  2. endoreg_db/mermaid/Overall_flow_patient_finding_intervention.md +10 -0
  3. endoreg_db/mermaid/anonymized_image_annotation.md +20 -0
  4. endoreg_db/mermaid/binary_classification_annotation.md +50 -0
  5. endoreg_db/mermaid/classification.md +8 -0
  6. endoreg_db/mermaid/examination.md +8 -0
  7. endoreg_db/mermaid/findings.md +7 -0
  8. endoreg_db/mermaid/image_classification.md +28 -0
  9. endoreg_db/mermaid/interventions.md +8 -0
  10. endoreg_db/mermaid/morphology.md +8 -0
  11. endoreg_db/mermaid/patient_creation.md +14 -0
  12. endoreg_db/mermaid/video_segmentation_annotation.md +17 -0
  13. endoreg_db/models/ai_model/ai_model.py +1 -1
  14. endoreg_db/models/ai_model/model_meta.py +1 -1
  15. endoreg_db/models/data_file/base_classes/utils.py +1 -1
  16. endoreg_db/serializers/raw_pdf_anony_text_validation.py +137 -0
  17. endoreg_db/serializers/raw_pdf_meta_validation.py +223 -0
  18. endoreg_db/serializers/raw_video_meta_validation.py +163 -1
  19. endoreg_db/serializers/video_segmentation.py +207 -112
  20. endoreg_db/urls.py +110 -11
  21. endoreg_db/views/raw_pdf_anony_text_validation_views.py +95 -0
  22. endoreg_db/views/raw_pdf_meta_validation_views.py +111 -0
  23. endoreg_db/views/raw_video_meta_validation_views.py +128 -18
  24. endoreg_db/views/video_segmentation_views.py +28 -11
  25. {endoreg_db-0.6.1.dist-info → endoreg_db-0.6.3.dist-info}/METADATA +11 -1
  26. {endoreg_db-0.6.1.dist-info → endoreg_db-0.6.3.dist-info}/RECORD +28 -13
  27. {endoreg_db-0.6.1.dist-info → endoreg_db-0.6.3.dist-info}/WHEEL +0 -0
  28. {endoreg_db-0.6.1.dist-info → endoreg_db-0.6.3.dist-info}/licenses/LICENSE +0 -0
endoreg_db/urls.py CHANGED
@@ -10,20 +10,23 @@ from .views.csrf import csrf_token_view
10
10
  #from .views.feature_selection_view import FetchSingleFramePredictionView // its implemented in ando-ai other project need to add here
11
11
  from .views.video_segmentation_views import VideoView, VideoLabelView,UpdateLabelSegmentsView
12
12
  from .views.views_for_timeline import video_timeline_view
13
- from .views.raw_video_meta_validation_views import VideoFileForMetaView
13
+ from .views.raw_video_meta_validation_views import VideoFileForMetaView, VideoFileForMetaView
14
+ from .views.raw_pdf_meta_validation_views import PDFFileForMetaView
15
+ from .views.raw_pdf_meta_validation_views import UpdateSensitiveMetaView
16
+ from .views.raw_pdf_anony_text_validation_views import RawPdfAnonyTextView, UpdateAnonymizedTextView
14
17
  router = DefaultRouter()
15
18
  router.register(r'patients', PatientViewSet)
16
19
 
20
+
17
21
  urlpatterns = [
18
22
  path('start-examination/', start_examination, name="start_examination"),
19
23
  path('get-location-choices/<int:location_id>/', get_location_choices, name="get_location_choices"),
20
24
  path('get-morphology-choices/<int:morphology_id>/', get_morphology_choices, name="get_morphology_choices"),
21
25
  path('api/', include(router.urls)),
22
26
  path('api/conf/', csrf_token_view, name='csrf_token'),
23
-
24
27
 
25
28
 
26
- #--------------------------------------VIDEO SEGMENTATION END POINTS--------------------------------------
29
+ #--------------------------------------START : VIDEO SEGMENTATION END POINTS--------------------------------------
27
30
 
28
31
  # The dropdown contains video names and their corresponding IDs, which are retrieved from the database(RawVideoFile). Additionally, this route(api/videos) also fetches labels along with their names and IDs from the label table.
29
32
  # We will modify this implementation later as per our requirements.
@@ -153,21 +156,117 @@ urlpatterns = [
153
156
  #
154
157
  path("api/video/<int:video_id>/label/<int:label_id>/update_segments/", UpdateLabelSegmentsView.as_view(), name="update_label_segments"),
155
158
 
156
- #----------------------------------END--VIDEO SEGMENTATION SECTION-------------------------------
157
- #this is for to test the timeline
158
- #need to delete this url and also endoreg_db_production/endoreg_db/views/views_for_timeline.py and endoreg_db_production/endoreg_db/templates/timeline.html
159
- path('video/<int:video_id>/timeline/', video_timeline_view, name='video_timeline'),
160
159
 
161
-
162
-
163
-
160
+ #----------------------------------START : SENSITIVE META AND RAWVIDEOFILE VIDEO PATIENT DETAILS-------------------------------
161
+
162
+ # API Endpoint for fetching video metadata or streaming the next available video
163
+ # This endpoint is used by the frontend to fetch:
164
+ # - The first available video if `last_id` is NOT provided.
165
+ # - The next available video where `id > last_id` if `last_id` is provided.
166
+ # - If `Accept: application/json` is set in headers, it returns video metadata as JSON.
167
+ # - If no videos are available, it returns {"error": "No more videos available."}.
164
168
  # const url = lastId ? `http://localhost:8000/api/video/meta/?last_id=${lastId}` : "http://localhost:8000/api/video/meta/";
165
169
  path("api/video/sensitivemeta/", VideoFileForMetaView.as_view(), name="video_meta"), # Single endpoint for both first and next video
166
- ]
167
170
 
168
171
 
169
172
 
173
+ # This API endpoint allows updating specific patient details (SensitiveMeta)
174
+ # linked to a video. It is used to correct or modify the patient's first name,
175
+ # last name, date of birth, and examination date.
176
+ # Fetch video metadata and update patient details
177
+ # The frontend should send a JSON request body like this:
178
+ # {
179
+ # "sensitive_meta_id": 2, # The ID of the SensitiveMeta entry (REQUIRED)
180
+ # "patient_first_name": "John", # New first name (REQUIRED, cannot be empty)
181
+ # "patient_last_name": "Doe", # New last name (REQUIRED, cannot be empty)
182
+ # "patient_dob": "1985-06-15", # New Date of Birth (REQUIRED, format YYYY-MM-DD)
183
+ # "examination_date": "2024-03-20" # New Examination Date (OPTIONAL, format YYYY-MM-DD)
184
+ # }
185
+ # - The frontend sends a PATCH request to this endpoint with updated patient data.
186
+ # - The backend validates the input using the serializer (`SensitiveMetaUpdateSerializer`).
187
+ # - If validation passes, the patient information is updated in the database.
188
+ # - If there are errors (e.g., missing fields, incorrect date format),
189
+ # the API returns structured error messages.
190
+ path("api/video/update_sensitivemeta/", VideoFileForMetaView.as_view(), name="update_patient_meta"),
191
+
192
+
193
+
194
+
195
+ #----------------------------------START : SENSITIVE META AND RAWPDFOFILE PDF PATIENT DETAILS-------------------------------
196
+
197
+ #The first request (without id) fetches the first available PDF metadata.
198
+ #The "Next" button (with id) fetches the next available PDF.
199
+ #If an id is provided, the API returns the actual PDF file instead of JSON.
200
+ path("api/pdf/sensitivemeta/", PDFFileForMetaView.as_view(), name="pdf_meta"),
201
+
202
+
203
+
204
+
205
+ # This API endpoint allows updating specific patient details (SensitiveMeta)
206
+ # linked to a PDF record. It enables modifying the patient's first name,
207
+ # last name, date of birth, and examination date.
208
+
209
+ # The frontend should send a JSON request body like this:
210
+ # {
211
+ # "sensitive_meta_id": 2, # The ID of the SensitiveMeta entry (REQUIRED)
212
+ # "patient_first_name": "John", # New first name (OPTIONAL, if provided, cannot be empty)
213
+ # "patient_last_name": "Doe", # New last name (OPTIONAL, if provided, cannot be empty)
214
+ # "patient_dob": "1985-06-15", # New Date of Birth (OPTIONAL, format YYYY-MM-DD)
215
+ # "examination_date": "2024-03-20" # New Examination Date (OPTIONAL, format YYYY-MM-DD)
216
+ # }
217
+
218
+ # - The frontend sends a PATCH request to this endpoint with the updated patient data.
219
+ # - The backend processes the request and updates only the fields that are provided.
220
+ # - If validation passes, the corresponding SensitiveMeta entry is updated in the database.
221
+ # - If errors occur (e.g., invalid ID, empty fields, incorrect date format),
222
+ # the API returns structured error messages.
223
+
224
+ path("api/pdf/update_sensitivemeta/", UpdateSensitiveMetaView.as_view(), name="update_pdf_meta"),
225
+
170
226
 
171
227
 
172
228
 
229
+
230
+ # API Endpoint for Fetching PDF Data (Including Anonymized Text)
231
+ # - This endpoint is used when the page loads.
232
+ # - Fetches the first available PDF (if no `last_id` is provided).
233
+ # - If `last_id` is given, fetches the next available PDF.
234
+ # - The frontend calls this endpoint on **page load** and when clicking the **next button**.
235
+ # Example frontend usage:
236
+ # const url = lastId ? `http://localhost:8000/api/pdf/anony_text/?last_id=${lastId}`
237
+ # : "http://localhost:8000/api/pdf/anony_text/";
238
+ path("api/pdf/anony_text/", RawPdfAnonyTextView.as_view(), name="pdf_anony_text"),
239
+
240
+ # API Endpoint for Updating the `anonymized_text` Field in `RawPdfFile`
241
+ # - This endpoint is called when the user edits the anonymized text and clicks **Save**.
242
+ # - Updates only the `anonymized_text` field for the specified PDF `id`.
243
+ # - The frontend sends a **PATCH request** to this endpoint with the updated text.
244
+ # Example frontend usage:
245
+ # axios.patch("http://localhost:8000/api/pdf/update_anony_text/", { id: 1, anonymized_text: "Updated text" });
246
+ path("api/pdf/update_anony_text/", UpdateAnonymizedTextView.as_view(), name="update_pdf_anony_text"),
247
+
248
+
249
+
250
+
251
+
252
+
253
+
254
+
255
+
256
+
257
+
258
+
259
+
260
+
261
+
262
+ #this is for, to test the timeline
263
+ #need to delete this url and also endoreg_db_production/endoreg_db/views/views_for_timeline.py and endoreg_db_production/endoreg_db/templates/timeline.html
264
+ path('video/<int:video_id>/timeline/', video_timeline_view, name='video_timeline'),
265
+ ]
266
+
267
+
173
268
  #https://biigle.de/manual/tutorials/videos/navigating-timeline#for time line example
269
+ from django.conf import settings
270
+ from django.conf.urls.static import static
271
+ if settings.DEBUG:
272
+ urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
@@ -0,0 +1,95 @@
1
+ from rest_framework.views import APIView
2
+ from rest_framework.response import Response
3
+ from rest_framework import status
4
+ from django.http import FileResponse, Http404
5
+ import os, mimetypes
6
+ from ..models import RawPdfFile
7
+ from ..serializers.raw_pdf_anony_text_validation import RawPdfAnonyTextSerializer
8
+
9
+ class RawPdfAnonyTextView(APIView):
10
+ """
11
+ API for:
12
+ - Fetching PDF metadata including `anonymized_text`.
13
+ - Fetching the next available PDF.
14
+ - Serving the actual PDF file.
15
+ """
16
+
17
+ def get(self, request):
18
+ """
19
+ Handles:
20
+ - First available PDF if `last_id` is NOT provided.
21
+ - Next available PDF if `last_id` is provided.
22
+ - Returns the actual PDF file if `id` is provided.
23
+ """
24
+
25
+ pdf_id = request.GET.get("id")
26
+ last_id = request.GET.get("last_id")
27
+
28
+ if pdf_id:
29
+ return self.serve_pdf_file(pdf_id)
30
+ else:
31
+ return self.fetch_pdf_metadata(last_id)
32
+
33
+ def fetch_pdf_metadata(self, last_id):
34
+ """
35
+ Fetches the next available PDF metadata, including `anonymized_text`.
36
+ """
37
+ pdf_entry = RawPdfAnonyTextSerializer.get_next_pdf(last_id)
38
+
39
+ if pdf_entry is None:
40
+ return Response({"error": "No more PDFs available."}, status=status.HTTP_404_NOT_FOUND)
41
+
42
+ serialized_pdf = RawPdfAnonyTextSerializer(pdf_entry, context={'request': self.request})
43
+ return Response(serialized_pdf.data, status=status.HTTP_200_OK)
44
+
45
+ def serve_pdf_file(self, pdf_id):
46
+ """
47
+ Serves the actual PDF file for viewing.
48
+ """
49
+ try:
50
+ pdf_entry = RawPdfFile.objects.get(id=pdf_id)
51
+ if not pdf_entry.file:
52
+ return Response({"error": "PDF file not found."}, status=status.HTTP_404_NOT_FOUND)
53
+
54
+ full_pdf_path = pdf_entry.file.path
55
+ if not os.path.exists(full_pdf_path):
56
+ raise Http404("PDF file not found on server.")
57
+
58
+ mime_type, _ = mimetypes.guess_type(full_pdf_path)
59
+ response = FileResponse(open(full_pdf_path, "rb"), content_type=mime_type or "application/pdf")
60
+ response["Content-Disposition"] = f'inline; filename="{os.path.basename(full_pdf_path)}"'
61
+ return response
62
+
63
+ except RawPdfFile.DoesNotExist:
64
+ return Response({"error": "Invalid PDF ID."}, status=status.HTTP_400_BAD_REQUEST)
65
+ except Exception as e:
66
+ return Response({"error": f"Internal error: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
67
+
68
+
69
+ class UpdateAnonymizedTextView(APIView):
70
+ """
71
+ API to update only `anonymized_text` in `RawPdfFile`
72
+ """
73
+
74
+ def patch(self, request):
75
+ """
76
+ Updates `anonymized_text` for a given `pdf_id`.
77
+ """
78
+ pdf_id = request.data.get("id")
79
+
80
+ if not pdf_id:
81
+ return Response({"error": "pdf_id is required."}, status=status.HTTP_400_BAD_REQUEST)
82
+
83
+ try:
84
+ pdf_entry = RawPdfFile.objects.get(id=pdf_id)
85
+ except RawPdfFile.DoesNotExist:
86
+ return Response({"error": "PDF not found."}, status=status.HTTP_404_NOT_FOUND)
87
+
88
+ serializer = RawPdfAnonyTextSerializer(pdf_entry, data=request.data, partial=True)
89
+
90
+ if serializer.is_valid():
91
+ serializer.save()
92
+ return Response({"message": "PDF anonymized_text updated successfully.", "updated_data": serializer.data},
93
+ status=status.HTTP_200_OK)
94
+
95
+ return Response({"error": "Invalid data.", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
@@ -0,0 +1,111 @@
1
+ from rest_framework.views import APIView
2
+ from rest_framework.response import Response
3
+ from rest_framework import status
4
+ from django.http import FileResponse, Http404
5
+ import mimetypes
6
+ import os
7
+ from ..models import RawPdfFile
8
+ from ..serializers.raw_pdf_meta_validation import PDFFileForMetaSerializer
9
+
10
+
11
+ class PDFFileForMetaView(APIView):
12
+ """
13
+ API endpoint to:
14
+ - Fetch PDF metadata if `id` is NOT provided.
15
+ - Serve the actual PDF file if `id` is provided.
16
+ """
17
+
18
+ def get(self, request):
19
+ """
20
+ Handles both:
21
+ Fetching PDF metadata** (if `id` is NOT provided)
22
+ Serving the actual PDF file** (if `id` is provided)
23
+ """
24
+
25
+ pdf_id = request.GET.get("id") # Check if 'id' is provided in the query params
26
+ last_id = request.GET.get("last_id") # Check if 'last_id' is provided for pagination
27
+
28
+ if pdf_id:
29
+ return self.serve_pdf_file(pdf_id) # Serve the actual PDF file
30
+ else:
31
+ return self.fetch_pdf_metadata(last_id) # Fetch metadata for the first or next PDF
32
+
33
+ def fetch_pdf_metadata(self, last_id):
34
+ """
35
+ Fetches the first or next available PDF metadata.
36
+ """
37
+ pdf_entry = PDFFileForMetaSerializer.get_next_pdf(last_id)
38
+
39
+ if pdf_entry is None:
40
+ return Response({"error": "No more PDFs available."}, status=status.HTTP_404_NOT_FOUND)
41
+
42
+ serialized_pdf = PDFFileForMetaSerializer(pdf_entry, context={'request': self.request})
43
+
44
+ print("Debugging API Response:")
45
+ print("Serialized Data:", serialized_pdf.data) # Debugging
46
+ return Response(serialized_pdf.data, status=status.HTTP_200_OK)
47
+
48
+ def serve_pdf_file(self, pdf_id):
49
+ """
50
+ Serves the actual PDF file for download or viewing.
51
+ """
52
+ try:
53
+ pdf_entry = RawPdfFile.objects.get(id=pdf_id) # Get the PDF file by ID
54
+
55
+ if not pdf_entry.file:
56
+ return Response({"error": "PDF file not found."}, status=status.HTTP_404_NOT_FOUND)
57
+
58
+ full_pdf_path = pdf_entry.file.path # Get the absolute file path
59
+
60
+ if not os.path.exists(full_pdf_path):
61
+ raise Http404("PDF file not found on server.")
62
+
63
+ mime_type, _ = mimetypes.guess_type(full_pdf_path) # Detect file type
64
+ response = FileResponse(open(full_pdf_path, "rb"), content_type=mime_type or "application/pdf")
65
+
66
+ response["Content-Disposition"] = f'inline; filename="{os.path.basename(full_pdf_path)}"' # Allows direct viewing
67
+
68
+ return response # Sends the PDF file as a stream
69
+
70
+ except RawPdfFile.DoesNotExist:
71
+ return Response({"error": "Invalid PDF ID."}, status=status.HTTP_400_BAD_REQUEST)
72
+
73
+ except Exception as e:
74
+ return Response({"error": f"Internal error: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
75
+
76
+ from rest_framework.views import APIView
77
+ from rest_framework.response import Response
78
+ from rest_framework import status
79
+ from ..models import SensitiveMeta
80
+ from ..serializers.raw_pdf_meta_validation import SensitiveMetaUpdateSerializer
81
+
82
+ class UpdateSensitiveMetaView(APIView):
83
+ """
84
+ API endpoint to update patient details in the SensitiveMeta table.
85
+ Handles partial updates (only edited fields).
86
+ """
87
+
88
+ def patch(self, request, *args, **kwargs):
89
+ """
90
+ Updates the provided fields for a specific patient record.
91
+ Only updates fields that are sent in the request.
92
+ """
93
+ sensitive_meta_id = request.data.get("sensitive_meta_id") # Required field
94
+
95
+ if not sensitive_meta_id:
96
+ return Response({"error": "sensitive_meta_id is required."}, status=status.HTTP_400_BAD_REQUEST)
97
+
98
+ try:
99
+ sensitive_meta = SensitiveMeta.objects.get(id=sensitive_meta_id)
100
+ except SensitiveMeta.DoesNotExist:
101
+ return Response({"error": "Patient record not found."}, status=status.HTTP_404_NOT_FOUND)
102
+
103
+ # Serialize the request data with partial=True to allow partial updates
104
+ serializer = SensitiveMetaUpdateSerializer(sensitive_meta, data=request.data, partial=True)
105
+
106
+ if serializer.is_valid():
107
+ serializer.save()
108
+ return Response({"message": "Patient information updated successfully.", "updated_data": serializer.data},
109
+ status=status.HTTP_200_OK)
110
+
111
+ return Response({"error": "Invalid data.", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
@@ -1,38 +1,148 @@
1
1
  from rest_framework.views import APIView
2
2
  from rest_framework.response import Response
3
3
  from rest_framework import status
4
+ from django.http import FileResponse, Http404
5
+ import mimetypes
6
+ import os
4
7
  from ..models import RawVideoFile
5
- from ..serializers.raw_video_meta_validation import VideoFileForMetaSerializer
8
+ from ..serializers.raw_video_meta_validation import VideoFileForMetaSerializer,SensitiveMetaUpdateSerializer
9
+ from ..models import SensitiveMeta
10
+
6
11
 
7
12
  class VideoFileForMetaView(APIView):
8
13
  """
9
14
  API endpoint to fetch video metadata step-by-step.
10
- If last_id is not provided Returns the first video.
11
- If last_id is given Returns the next available video.
15
+ Uses the serializer to get the first or next available video.
12
16
  """
13
17
 
14
- ##need to change this fucntion , like the previous one
15
-
16
18
  def get(self, request):
17
19
  """
18
- Handles:
19
- First video if last_id is nt in query params.
20
- Next video where id > last_id` if provided.
20
+ - Fetches the **first available video** if `last_id` is NOT provided.
21
+ - Fetches the **next available video** where `id > last_id` if provided.
22
+ - If no video is available, returns a structured error response.
21
23
  """
22
- last_id = request.GET.get("last_id") # Get last_id from query params (e.g., ?last_id=2)
24
+ last_id = request.GET.get("last_id") # Get last_id from query params
25
+
26
+ # Get the next video as a model instance
27
+ video_entry = VideoFileForMetaSerializer.get_next_video(last_id)
28
+
29
+ if video_entry is None:
30
+ return Response({"error": "No more videos available."}, status=status.HTTP_404_NOT_FOUND)
31
+
32
+ serialized_video = VideoFileForMetaSerializer(video_entry, context={'request': request})
33
+
34
+ # Check if required fields are missing
35
+ response_data = serialized_video.data
36
+ missing_fields = {}
37
+
38
+ if response_data.get('file') is None:
39
+ missing_fields['file'] = "No file associated with this entry."
40
+
41
+ if response_data.get('video_url') is None:
42
+ missing_fields['video_url'] = "Video file is missing."
43
+
44
+ if response_data.get('full_video_path') is None:
45
+ missing_fields['full_video_path'] = "No file path found on server."
23
46
 
47
+ if not response_data.get('patient_first_name'):
48
+ missing_fields['patient_first_name'] = "Patient first name is missing."
49
+
50
+ if not response_data.get('patient_last_name'):
51
+ missing_fields['patient_last_name'] = "Patient last name is missing."
52
+
53
+ if not response_data.get('patient_dob'):
54
+ missing_fields['patient_dob'] = "Patient date of birth is missing."
55
+
56
+ if not response_data.get('examination_date'):
57
+ missing_fields['examination_date'] = "Examination date is missing."
58
+
59
+ if response_data.get('duration') is None:
60
+ missing_fields['duration'] = "Unable to determine video duration. The file might be corrupted or unreadable."
61
+
62
+ if missing_fields:
63
+ return Response({"error": "Missing required data.", "details": missing_fields},
64
+ status=status.HTTP_400_BAD_REQUEST)
65
+
66
+ return Response(serialized_video.data, status=status.HTTP_200_OK)
67
+
68
+ def serve_video_file(self, video_entry):
69
+ """
70
+ Streams the video file dynamically.
71
+ """
24
72
  try:
25
- # If last_id is provided, fetch the next video where id > last_id
26
- # id__gt is orm syntax which is equal to SELECT * FROM rawvideofile WHERE id > 2 ORDER BY id ASC LIMIT 1;
73
+ full_video_path = video_entry.file.path # Get file path
27
74
 
28
- query_filter = {} if last_id is None else {"id__gt": int(last_id)}
29
- video_entry = RawVideoFile.objects.select_related("sensitive_meta").filter(**query_filter).order_by('id').first()
75
+ if not os.path.exists(full_video_path):
76
+ raise Http404("Video file not found.")
30
77
 
31
- if not video_entry:
32
- return Response({"message": "No more videos available."}, status=status.HTTP_404_NOT_FOUND)
78
+ mime_type, _ = mimetypes.guess_type(full_video_path) # Detects file type
79
+ response = FileResponse(open(full_video_path, "rb"), content_type=mime_type or "video/mp4")
33
80
 
34
- serializer = VideoFileForMetaSerializer(video_entry)
35
- return Response(serializer.data, status=status.HTTP_200_OK)
81
+ response["Content-Disposition"] = f'inline; filename="{os.path.basename(full_video_path)}"' # Allows direct streaming
82
+
83
+ return response # Sends the video file as a stream
36
84
 
37
85
  except Exception as e:
38
- return Response({"error": f"Internal server error: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
86
+ return Response({"error": f"Internal error: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
87
+
88
+
89
+ def patch(self, request, *args, **kwargs):
90
+ """
91
+ Calls the serializer to update `SensitiveMeta` data.
92
+ """
93
+
94
+ # Ensure all required fields are provided
95
+ required_fields = ["sensitive_meta_id", "patient_first_name", "patient_last_name", "patient_dob", "examination_date"]
96
+ missing_fields = [field for field in required_fields if field not in request.data]
97
+
98
+ if missing_fields:
99
+ return Response({"error": "Missing required fields", "missing_fields": missing_fields}, status=status.HTTP_400_BAD_REQUEST)
100
+
101
+ # Call serializer for validation
102
+ serializer = SensitiveMetaUpdateSerializer(data=request.data, partial=True)
103
+
104
+ if serializer.is_valid():
105
+ # Get the instance and update it
106
+ sensitive_meta = SensitiveMeta.objects.get(id=request.data["sensitive_meta_id"])
107
+ updated_instance = serializer.update(sensitive_meta, serializer.validated_data)
108
+
109
+ return Response({
110
+ "message": "Patient information updated successfully.",
111
+ "updated_data": SensitiveMetaUpdateSerializer(updated_instance).data
112
+ }, status=status.HTTP_200_OK)
113
+
114
+ # Return validation errors
115
+ return Response({"error": "Invalid data.", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
116
+
117
+
118
+ """
119
+ await import('https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js');
120
+ const updatePatientInfo = async () => {
121
+ const updatedData = {
122
+ sensitive_meta_id: 2,
123
+ patient_first_name: "Placeholder",
124
+ patient_last_name: "Placeholder",
125
+ patient_dob: "1994-06-15",
126
+ examination_date: "2024-06-15"
127
+ };
128
+
129
+ try {
130
+ const response = await axios.patch("http://localhost:8000/api/video/update_sensitivemeta/", updatedData, {
131
+ headers: { "Content-Type": "application/json" }
132
+ });
133
+
134
+ console.log("Update Success:", response.data);
135
+ alert("Patient information updated successfully!");
136
+
137
+ return response.data;
138
+ } catch (error) {
139
+ console.error("Update Error:", error.response?.data || error);
140
+ alert("Failed to update patient information.");
141
+ return error.response?.data || { error: "Unknown error" };
142
+ }
143
+ };
144
+
145
+
146
+ updatePatientInfo().then(response => console.log("Final Response:", response));
147
+
148
+ """
@@ -31,9 +31,14 @@ class VideoView(APIView):
31
31
  Returns a list of all available videos along with available labels.
32
32
  Used to populate the video selection dropdown in Vue.js.
33
33
  """
34
+
34
35
  videos = RawVideoFile.objects.all()
35
36
  labels = Label.objects.all() # Fetch all labels
36
37
 
38
+ if not videos.exists():
39
+ return Response({"error": "No videos found in the database."}, status=status.HTTP_404_NOT_FOUND)
40
+
41
+
37
42
  video_serializer = VideoListSerializer(videos, many=True)
38
43
  label_serializer = LabelSerializer(labels, many=True) # Serialize labels
39
44
 
@@ -134,16 +139,28 @@ class UpdateLabelSegmentsView(APIView):
134
139
 
135
140
  def put(self, request, video_id, label_id):
136
141
  """
137
- Handles PUT request to update or create label segments.
142
+ Updates segments for a given video & label.
138
143
  """
139
- serializer = LabelSegmentUpdateSerializer(data=request.data)
140
144
 
141
- if serializer.is_valid():
142
- result = serializer.save()
143
- return Response({
144
- "message": "Segments updated successfully",
145
- "updated_segments": result["updated_segments"],
146
- "new_segments": result["new_segments"]
147
- }, status=status.HTTP_200_OK)
148
-
149
- return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
145
+ # Ensure required fields are provided
146
+ required_fields = ["video_id", "label_id", "segments"]
147
+ missing_fields = [field for field in required_fields if field not in request.data]
148
+
149
+ if missing_fields:
150
+ return Response({"error": "Missing required fields", "missing": missing_fields}, status=status.HTTP_400_BAD_REQUEST)
151
+
152
+ # Validate input data
153
+ serializer = LabelSegmentUpdateSerializer(data=request.data, partial=True)
154
+
155
+ if not serializer.is_valid():
156
+ return Response({"error": "Invalid segment data", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
157
+
158
+ # Process and save segment updates
159
+ result = serializer.save()
160
+
161
+ return Response({
162
+ "message": "Segments updated successfully.",
163
+ "updated_segments": result["updated_segments"],
164
+ "new_segments": result["new_segments"],
165
+ "deleted_segments": result["deleted_segments"]
166
+ }, status=status.HTTP_200_OK)
@@ -1,8 +1,18 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: endoreg-db
3
- Version: 0.6.1
3
+ Version: 0.6.3
4
4
  Summary: EndoReg Db Django App
5
+ Project-URL: Homepage, https://info.coloreg.de
6
+ Project-URL: Repository, https://github.com/wg-lux/endoreg-db
7
+ Author: Max Hild, Hamza Zahid, Peter Kowalczyk
8
+ Author-email: "Thomas J. Lux" <lux_t1@ukw.de>
9
+ Maintainer: Max Hild, Hamza Zahid, Peter Kowalczyk
10
+ Maintainer-email: "Thomas J. Lux" <lux_t1@ukw.de>
5
11
  License-File: LICENSE
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
6
16
  Requires-Python: >=3.11
7
17
  Requires-Dist: agl-report-reader>=0.4.0
8
18
  Requires-Dist: django-bootstrap5>=24.3