This page documents the medical imaging feature for the GP Booking App, which allows staff to upload and view X-rays, CT scans, MRIs, and other medical images within patient records.
Images are stored on the principal VPS filesystem with a Docker volume mount (/var/www/html/gp_booking_app/media/). A MinIO instance is running and ready for per-client S3 migration when needed.
Browser → gp.veripath.co.uk → nginx proxy → Django app → Filesystem
(Docker volume)
Future architecture (when per-client MinIO is deployed):
Browser → gp.veripath.co.uk → Django app (generates pre-signed URL)
↓
Browser → {slug}-storage.veripath.co.uk → MinIO on Client VPS
| Field | Type | Description |
|---|---|---|
| patient | FK → CustomUser | Patient the image belongs to |
| appointment | FK → Appointment (nullable) | Optional linked appointment |
| title | CharField | User-friendly label |
| image_type | ChoiceField | XRAY, CT, MRI, ULTRASOUND, PHOTO, DICOM, OTHER |
| file | FileField | Uploaded image/DICOM file |
| file_size | BigIntegerField | Size in bytes |
| file_hash | CharField(64) | SHA-256 hash |
| mime_type | CharField | MIME type |
| notes | EncryptedTextField | Clinician notes about the image |
| dicom_metadata | JSONField | Parsed DICOM tags |
| uploaded_by | FK → CustomUser | Who uploaded it |
| org_id | CharField | Organisation scoping |
| Format | MIME Type | In-Browser Viewing |
|---|---|---|
| JPEG/PNG/BMP/TIFF | image/* | Inline image tag |
| DICOM (.dcm) | application/dicom | CornerstoneJS viewer |
| ZIP (.zip) | application/zip | Auto-extracted, individual files processed |
DICOM files are rendered in-browser using CornerstoneJS with the following capabilities:
The viewer loads DICOM pixel data via the internal API endpoint at /clinical/api/images/<id>/dicom-data/.
CDN libraries loaded:
| Method | URL | Description |
|---|---|---|
| GET | /clinical/api/images/ |
List images (filter by ?patient=<id>) |
| POST | /clinical/api/images/ |
Upload image (multipart form) |
| GET | /clinical/api/images/<id>/ |
Get image metadata |
| DELETE | /clinical/api/images/<id>/ |
Delete image |
| GET | /clinical/api/images/<id>/download/ |
Download image file |
| GET | /clinical/api/images/<id>/dicom-data/ |
DICOM pixel data for CornerstoneJS |
| GET | /clinical/api/images/by-patient/<id>/ |
All images for a patient |
| URL | Purpose | User Role |
|---|---|---|
/clinical/images/patient/<id>/ |
Gallery of patient's images | All staff |
/clinical/images/upload/<id>/ |
Drag-drop upload form | Clinicians, Receptionists |
/clinical/images/<id>/ |
Detail view with CornerstoneJS | All staff |
/admin/clinical_data/patientimage/ |
Admin interface | ADMIN |
Medical Images links are present on:
| Page | Location |
|---|---|
| Patient Detail (clinician view) | users/patient_detail.html — Quick Actions |
| Patient Detail (receptionist view) | dashboards/receptionist_patient_detail.html — Quick Actions |
| Clinician Dashboard | dashboards/clinician_dashboard.html — next to "View Record" in appointment rows |
| Patient Dashboard | dashboards/patient_dashboard.html — Quick Actions ("My Images") |
dsp_clinic/settings.py)MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
MAX_UPLOAD_SIZE = 100 * 1024 * 1024 # 100MB
FILE_UPLOAD_MAX_MEMORY_SIZE = MAX_UPLOAD_SIZE
DATA_UPLOAD_MAX_MEMORY_SIZE = MAX_UPLOAD_SIZE * 2
gp.veripath.co.uk.conf)client_max_body_size 100M;
To switch to S3/MinIO storage, uncomment the S3 configuration block in settings.py and set:
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_STORAGE_BUCKET_NAME = 'patient-images'
AWS_S3_ENDPOINT_URL = 'http://minio:9000'
All imaging code is in /var/www/html/gp_booking_app/clinical_data/:
| File | Purpose |
|---|---|
models.py |
PatientImage model (lines 546-609) |
image_utils.py |
DICOM parsing, file validation, ZIP extraction, MIME detection |
api/serializers.py |
PatientImageSerializer, PatientImageListSerializer (lines 100-235) |
api/views.py |
PatientImageViewSet with CRUD + download + dicom-data actions |
views.py |
Template-based list, upload, detail views (lines 403-446) |
urls.py |
URL routing for both API and template views |
admin.py |
PatientImageAdmin with search, filter, fieldsets |
Templates are at /var/www/html/gp_booking_app/templates/clinical_data/:
| Template | Purpose |
|---|---|
patient_image_list.html |
Gallery grid with type badges, pagination |
patient_image_upload.html |
Drag-drop upload with ZIP support |
patient_image_detail.html |
Image preview + metadata + CornerstoneJS viewer |
| Feature | Status |
|---|---|
| Upload (drag-drop, ZIP) | Done |
| Gallery list | Done |
| Detail view with metadata | Done |
| DICOM CornerstoneJS viewer | Done |
| Admin integration | Done |
| Navigation links | Done |
| Per-client MinIO storage | Ready (container running, config commented out) |
| DICOMweb endpoints (STOW-RS/WADO-RS) | Future |
| NHSmail export pipeline | Future |
| OHIF Viewer (advanced) | Future |
| Date | Change |
|---|---|
| 2026-06-10 | Initial implementation: upload, gallery, detail, CornerstoneJS viewer |