rinogeek commited on
Commit
1624b73
·
0 Parent(s):

Initial Docker configuration for Hugging Face

Browse files
.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ best.pt filter=lfs diff=lfs merge=lfs -text
DEPLOYMENT_HF.md ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Documentation du Déploiement Backend sur Hugging Face (Docker)
2
+
3
+ Cette documentation explique les modifications apportées au dossier `backend` pour permettre son déploiement sur Hugging Face Spaces en utilisant Docker.
4
+
5
+ ## 1. Fichiers Ajoutés
6
+
7
+ ### `Dockerfile`
8
+ Le fichier `Dockerfile` est le cœur de la configuration Docker. Il effectue les actions suivantes :
9
+ - Utilise une image de base Python 3.10.
10
+ - Installe les dépendances système nécessaires à OpenCV (`libgl1-mesa-glx`, `libglib2.0-0`).
11
+ - Installe les dépendances Python listées dans `requirements.txt`.
12
+ - Configure le port par défaut sur `7860` (obligatoire pour Hugging Face Spaces).
13
+ - Exécute les migrations de base de données au démarrage.
14
+
15
+ ### `README_HF.md`
16
+ Ce fichier contient les métadonnées YAML nécessaires à Hugging Face pour identifier le SDK (Docker) et le port de l'application.
17
+ **Note :** Pour que Hugging Face reconnaisse ces métadonnées, ce contenu doit être présent dans le fichier `README.md` à la racine du dépôt sur Hugging Face.
18
+
19
+ ## 2. Modifications de Configuration
20
+
21
+ ### Port de l'Application
22
+ Hugging Face Spaces expose l'application sur le port **7860**. Le `Dockerfile` est configuré pour lancer le serveur Django sur ce port spécifique :
23
+ `python manage.py runserver 0.0.0.0:7860`
24
+
25
+ ### Gestion des Fichiers Statiques et Media
26
+ Dans un environnement Docker éphémère comme Hugging Face Spaces :
27
+ - Les fichiers media (images uploadées) seront stockés localement dans le conteneur mais seront perdus au redémarrage du Space.
28
+ - Pour une utilisation en production réelle, un stockage externe (comme AWS S3 ou Google Cloud Storage) serait recommandé.
29
+
30
+ ## 3. Procédure d'Upload
31
+
32
+ Pour uploader le backend sur votre Space `SATCAP-OCEANS_DOCKER` :
33
+
34
+ 1. **Initialiser Git (si ce n'est pas déjà fait)** :
35
+ ```bash
36
+ cd backend
37
+ git init
38
+ ```
39
+
40
+ 2. **Ajouter le remote Hugging Face** :
41
+ ```bash
42
+ git remote add hf https://huggingface.co/spaces/CosmoLABHub/SATCAP-OCEANS_DOCKER
43
+ ```
44
+
45
+ 3. **Préparer le README** :
46
+ Copiez le contenu de `README_HF.md` dans un fichier nommé `README.md` (Hugging Face a besoin du nom exact `README.md`).
47
+
48
+ 4. **Pousser vers Hugging Face** :
49
+ ```bash
50
+ git add .
51
+ git commit -m "Configuration Docker pour Hugging Face"
52
+ git push hf main --force
53
+ ```
54
+
55
+ ## 4. Utilisation comme API
56
+
57
+ Une fois le Space "Running", l'URL de l'API sera :
58
+ `https://cosmolabhub-satcap-oceans-docker.hf.space/api/detect/`
59
+
60
+ Vous pouvez utiliser cette URL dans votre frontend pour envoyer des requêtes de détection.
Dockerfile ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use an official Python runtime as a parent image
2
+ FROM python:3.10-slim
3
+
4
+ # Set environment variables
5
+ ENV PYTHONDONTWRITEBYTECODE 1
6
+ ENV PYTHONUNBUFFERED 1
7
+ ENV PORT 7860
8
+
9
+ # Set work directory
10
+ WORKDIR /app
11
+
12
+ # Install system dependencies
13
+ RUN apt-get update && apt-get install -y \
14
+ libgl1-mesa-glx \
15
+ libglib2.0-0 \
16
+ git \
17
+ && rm -rf /var/lib/apt/lists/*
18
+
19
+ # Install dependencies
20
+ COPY requirements.txt /app/
21
+ RUN pip install --no-cache-dir -r requirements.txt
22
+
23
+ # Copy project
24
+ COPY . /app/
25
+
26
+ # Create media and static directories
27
+ RUN mkdir -p /app/media /app/static
28
+
29
+ # Run migrations (using SQLite for simplicity in Space)
30
+ RUN python manage.py migrate
31
+
32
+ # Expose the port Gradio/Hugging Face expects
33
+ EXPOSE 7860
34
+
35
+ # Start the application using Gunicorn or directly with manage.py
36
+ # Hugging Face Spaces for Docker expects the app to run on port 7860
37
+ CMD ["python", "manage.py", "runserver", "0.0.0.0:7860"]
README.md ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: SATCAP-OCEANS Backend
3
+ emoji: 🚀
4
+ colorFrom: blue
5
+ colorTo: gray
6
+ sdk: docker
7
+ app_port: 7860
8
+ pinned: false
9
+ license: mit
10
+ ---
11
+
12
+ # SATCAP-OCEANS Backend (API)
13
+
14
+ Ce dépôt contient le backend Django du projet SATCAP-OCEANS, configuré pour être déployé sur Hugging Face Spaces via Docker.
15
+
16
+ ## Configuration pour Hugging Face
17
+
18
+ Le backend a été modifié pour fonctionner dans un environnement Docker sur Hugging Face :
19
+ - **Port** : L'application écoute sur le port `7860` (requis par Hugging Face).
20
+ - **Base de données** : Utilise SQLite par défaut pour la portabilité.
21
+ - **Dockerfile** : Inclus pour l'installation automatique des dépendances système (OpenCV, etc.) et Python.
22
+
23
+ ## Utilisation de l'API
24
+
25
+ Une fois déployé, vous pouvez accéder à l'API via l'URL de votre Space.
26
+
27
+ ### Endpoints principaux :
28
+ - `POST /api/detect/` : Envoyer une image pour détection.
29
+ - `GET /api/history/` : Récupérer l'historique des détections.
30
+
31
+ ## Déploiement
32
+
33
+ Pour mettre à jour ce Space :
34
+ 1. Ajoutez ce dépôt comme remote : `git remote add hf_docker https://huggingface.co/spaces/CosmoLABHub/SATCAP-OCEANS_DOCKER`
35
+ 2. Poussez les changements : `git push hf_docker main`
README_HF.md ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: SATCAP-OCEANS Backend
3
+ emoji: 🚀
4
+ colorFrom: blue
5
+ colorTo: gray
6
+ sdk: docker
7
+ app_port: 7860
8
+ pinned: false
9
+ license: mit
10
+ ---
11
+
12
+ # SATCAP-OCEANS Backend (API)
13
+
14
+ Ce dépôt contient le backend Django du projet SATCAP-OCEANS, configuré pour être déployé sur Hugging Face Spaces via Docker.
15
+
16
+ ## Configuration pour Hugging Face
17
+
18
+ Le backend a été modifié pour fonctionner dans un environnement Docker sur Hugging Face :
19
+ - **Port** : L'application écoute sur le port `7860` (requis par Hugging Face).
20
+ - **Base de données** : Utilise SQLite par défaut pour la portabilité.
21
+ - **Dockerfile** : Inclus pour l'installation automatique des dépendances système (OpenCV, etc.) et Python.
22
+
23
+ ## Utilisation de l'API
24
+
25
+ Une fois déployé, vous pouvez accéder à l'API via l'URL de votre Space.
26
+
27
+ ### Endpoints principaux :
28
+ - `POST /api/detect/` : Envoyer une image pour détection.
29
+ - `GET /api/history/` : Récupérer l'historique des détections.
30
+
31
+ ## Déploiement
32
+
33
+ Pour mettre à jour ce Space :
34
+ 1. Ajoutez ce dépôt comme remote : `git remote add hf_docker https://huggingface.co/spaces/CosmoLABHub/SATCAP-OCEANS_DOCKER`
35
+ 2. Poussez les changements : `git push hf_docker main`
api/__init__.py ADDED
File without changes
api/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (198 Bytes). View file
 
api/__pycache__/admin.cpython-312.pyc ADDED
Binary file (4.04 kB). View file
 
api/__pycache__/models.cpython-312.pyc ADDED
Binary file (1.36 kB). View file
 
api/__pycache__/serializers.cpython-312.pyc ADDED
Binary file (741 Bytes). View file
 
api/__pycache__/stats_views.cpython-312.pyc ADDED
Binary file (1.38 kB). View file
 
api/__pycache__/urls.cpython-312.pyc ADDED
Binary file (677 Bytes). View file
 
api/__pycache__/utils.cpython-312.pyc ADDED
Binary file (2.15 kB). View file
 
api/__pycache__/views.cpython-312.pyc ADDED
Binary file (2.71 kB). View file
 
api/admin.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.contrib import admin
2
+ from django.utils.html import format_html
3
+ from .models import Detection
4
+ from .utils import run_detection
5
+ import json
6
+
7
+ @admin.register(Detection)
8
+ class DetectionAdmin(admin.ModelAdmin):
9
+ list_display = ('id', 'thumbnail', 'user', 'object_count', 'top_labels', 'created_at')
10
+ list_filter = ('created_at', 'user')
11
+ search_fields = ('results', 'user__username')
12
+ readonly_fields = ('thumbnail_large', 'formatted_results', 'created_at')
13
+ actions = ['re_analyze_detections']
14
+
15
+ def thumbnail(self, obj):
16
+ if obj.image:
17
+ return format_html('<img src="{}" style="width: 50px; height: auto; border-radius: 4px;" />', obj.image.url)
18
+ return "No Image"
19
+ thumbnail.short_description = 'Preview'
20
+
21
+ def thumbnail_large(self, obj):
22
+ if obj.image:
23
+ return format_html('<img src="{}" style="max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);" />', obj.image.url)
24
+ return "No Image"
25
+ thumbnail_large.short_description = 'Image View'
26
+
27
+ def object_count(self, obj):
28
+ return len(obj.results) if obj.results else 0
29
+ object_count.short_description = 'Objects Found'
30
+
31
+ def top_labels(self, obj):
32
+ if not obj.results:
33
+ return "-"
34
+ labels = [item['label'] for item in obj.results]
35
+ unique_labels = list(set(labels))
36
+ return ", ".join(unique_labels[:3]) + ("..." if len(unique_labels) > 3 else "")
37
+ top_labels.short_description = 'Main Detections'
38
+
39
+ def formatted_results(self, obj):
40
+ return format_html('<pre style="background: #f4f4f4; padding: 10px; border-radius: 4px; max-height: 400px; overflow: auto;">{}</pre>',
41
+ json.dumps(obj.results, indent=2))
42
+ formatted_results.short_description = 'Analysis Data (JSON)'
43
+
44
+ @admin.action(description='Re-analyze selected detections with AI')
45
+ def re_analyze_detections(self, request, queryset):
46
+ count = 0
47
+ for obj in queryset:
48
+ if obj.image:
49
+ detections = run_detection(obj.image.path)
50
+ obj.results = detections
51
+ obj.save()
52
+ count += 1
53
+ self.message_user(request, f"Successfully re-analyzed {count} images.")
54
+
55
+ fieldsets = (
56
+ ('General Information', {
57
+ 'fields': ('user', 'image', 'created_at')
58
+ }),
59
+ ('Visual Analysis', {
60
+ 'fields': ('thumbnail_large',)
61
+ }),
62
+ ('Detailed Results', {
63
+ 'fields': ('formatted_results',),
64
+ 'classes': ('collapse',)
65
+ }),
66
+ )
api/migrations/0001_initial.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 6.0 on 2026-01-03 17:13
2
+
3
+ import django.db.models.deletion
4
+ from django.conf import settings
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ initial = True
11
+
12
+ dependencies = [
13
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
14
+ ]
15
+
16
+ operations = [
17
+ migrations.CreateModel(
18
+ name='Detection',
19
+ fields=[
20
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21
+ ('image', models.ImageField(upload_to='detections/')),
22
+ ('results', models.JSONField()),
23
+ ('created_at', models.DateTimeField(auto_now_add=True)),
24
+ ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
25
+ ],
26
+ ),
27
+ ]
api/migrations/__init__.py ADDED
File without changes
api/migrations/__pycache__/0001_initial.cpython-312.pyc ADDED
Binary file (1.61 kB). View file
 
api/migrations/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (209 Bytes). View file
 
api/models.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.db import models
2
+ from django.contrib.auth.models import User
3
+
4
+ class Detection(models.Model):
5
+ user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
6
+ image = models.ImageField(upload_to='detections/')
7
+ results = models.JSONField() # Stores the list of detected objects
8
+ created_at = models.DateTimeField(auto_now_add=True)
9
+
10
+ def __str__(self):
11
+ count = len(self.results) if self.results else 0
12
+ return f"Detection {self.id} ({count} objects) - {self.created_at.strftime('%Y-%m-%d %H:%M')}"
api/serializers.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from rest_framework import serializers
2
+ from .models import Detection
3
+
4
+ class DetectionSerializer(serializers.ModelSerializer):
5
+ class Meta:
6
+ model = Detection
7
+ fields = '__all__'
api/stats_views.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from rest_framework.views import APIView
2
+ from rest_framework.response import Response
3
+ from .models import Detection
4
+ from django.db.models import Count
5
+ from collections import Counter
6
+
7
+ class StatsView(APIView):
8
+ def get(self, request):
9
+ detections = Detection.objects.all()
10
+ total_detections = detections.count()
11
+
12
+ # Count labels across all detections
13
+ label_counts = Counter()
14
+ for det in detections:
15
+ for item in det.results:
16
+ label_counts[item['label']] += 1
17
+
18
+ return Response({
19
+ "total_images_analyzed": total_detections,
20
+ "total_objects_detected": sum(label_counts.values()),
21
+ "label_distribution": dict(label_counts)
22
+ })
api/urls.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from django.urls import path
2
+ from .views import DetectView, DetectionHistoryView
3
+ from .stats_views import StatsView
4
+
5
+ urlpatterns = [
6
+ path('detect/', DetectView.as_view(), name='detect'),
7
+ path('history/', DetectionHistoryView.as_view(), name='history'),
8
+ path('stats/', StatsView.as_view(), name='stats'),
9
+ ]
api/utils.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import os
4
+ from django.conf import settings
5
+ from ultralytics import YOLO
6
+
7
+ # Global model variable
8
+ _model = None
9
+
10
+ def get_model():
11
+ global _model
12
+ if _model is None:
13
+ MODEL_PATH = os.path.join(settings.BASE_DIR, 'best.pt')
14
+ try:
15
+ _model = YOLO(MODEL_PATH)
16
+ except Exception as e:
17
+ print(f"Error loading model: {e}")
18
+ return _model
19
+
20
+ def run_detection(image_path):
21
+ """
22
+ Runs YOLO detection on an image file path and returns a list of detections.
23
+ """
24
+ model = get_model()
25
+ if model is None:
26
+ return []
27
+
28
+ img = cv2.imread(image_path)
29
+ if img is None:
30
+ return []
31
+
32
+ results = model(img)
33
+ detections = []
34
+
35
+ for r in results:
36
+ boxes = r.boxes
37
+ for box in boxes:
38
+ # Get coordinates in percentage for the frontend
39
+ x_center, y_center, w, h = box.xywhn[0].tolist()
40
+
41
+ x = (x_center - w/2) * 100
42
+ y = (y_center - h/2) * 100
43
+ width = w * 100
44
+ height = h * 100
45
+
46
+ conf = float(box.conf[0])
47
+ cls = int(box.cls[0])
48
+ label = model.names[cls]
49
+
50
+ detections.append({
51
+ "id": len(detections),
52
+ "x": x,
53
+ "y": y,
54
+ "width": width,
55
+ "height": height,
56
+ "label": label,
57
+ "confidence": conf * 100
58
+ })
59
+
60
+ return detections
api/views.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from rest_framework.views import APIView
2
+ from rest_framework.response import Response
3
+ from rest_framework import status
4
+ from .models import Detection
5
+ from .serializers import DetectionSerializer
6
+ from django.core.files.base import ContentFile
7
+ import cv2
8
+ import numpy as np
9
+ from ultralytics import YOLO
10
+ import os
11
+ from django.conf import settings
12
+
13
+ from .utils import run_detection
14
+
15
+ class DetectView(APIView):
16
+ def post(self, request):
17
+ if 'image' not in request.FILES:
18
+ return Response({"error": "No image provided"}, status=status.HTTP_400_BAD_REQUEST)
19
+
20
+ image_file = request.FILES['image']
21
+
22
+ # Save temporarily to run detection or use the file directly
23
+ # For simplicity and consistency with the utility, we save the object first with empty results
24
+ # then run detection on the saved file path.
25
+
26
+ detection_obj = Detection.objects.create(
27
+ image=image_file,
28
+ results=[],
29
+ user=request.user if request.user.is_authenticated else None
30
+ )
31
+
32
+ # Run detection on the saved file
33
+ detections = run_detection(detection_obj.image.path)
34
+
35
+ # Update results
36
+ detection_obj.results = detections
37
+ detection_obj.save()
38
+
39
+ return Response(DetectionSerializer(detection_obj).data, status=status.HTTP_201_CREATED)
40
+
41
+ class DetectionHistoryView(APIView):
42
+ def get(self, request):
43
+ if request.user.is_authenticated:
44
+ detections = Detection.objects.filter(user=request.user).order_by('-created_at')
45
+ else:
46
+ detections = Detection.objects.all().order_by('-created_at')[:10] # Last 10 for guests
47
+
48
+ serializer = DetectionSerializer(detections, many=True)
49
+ return Response(serializer.data)
best.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8895d0ddf2db84fcd858cd4d6b7a15f0402b8b2125b29a1e3214cb3785644d73
3
+ size 52039826
manage.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ import os
3
+ import sys
4
+
5
+ def main():
6
+ """Run administrative tasks."""
7
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'satcap_project.settings')
8
+ try:
9
+ from django.core.management import execute_from_command_line
10
+ except ImportError as exc:
11
+ raise ImportError(
12
+ "Couldn't import Django. Are you sure it's installed and "
13
+ "available on your PYTHONPATH environment variable? Did you "
14
+ "forget to activate a virtual environment?"
15
+ ) from exc
16
+ execute_from_command_line(sys.argv)
17
+
18
+ if __name__ == '__main__':
19
+ main()
requirements.txt ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ asgiref==3.11.0
2
+ certifi==2025.11.12
3
+ charset-normalizer==3.4.4
4
+ contourpy==1.3.3
5
+ cycler==0.12.1
6
+ Django==6.0
7
+ django-cors-headers==4.9.0
8
+ djangorestframework==3.16.1
9
+ filelock==3.20.2
10
+ fonttools==4.61.1
11
+ fsspec==2025.12.0
12
+ idna==3.11
13
+ Jinja2==3.1.6
14
+ kiwisolver==1.4.9
15
+ MarkupSafe==3.0.3
16
+ matplotlib==3.10.8
17
+ mpmath==1.3.0
18
+ networkx==3.6.1
19
+ numpy==2.2.6
20
+ nvidia-cublas-cu12==12.8.4.1
21
+ nvidia-cuda-cupti-cu12==12.8.90
22
+ nvidia-cuda-nvrtc-cu12==12.8.93
23
+ nvidia-cuda-runtime-cu12==12.8.90
24
+ nvidia-cudnn-cu12==9.10.2.21
25
+ nvidia-cufft-cu12==11.3.3.83
26
+ nvidia-cufile-cu12==1.13.1.3
27
+ nvidia-curand-cu12==10.3.9.90
28
+ nvidia-cusolver-cu12==11.7.3.90
29
+ nvidia-cusparse-cu12==12.5.8.93
30
+ nvidia-cusparselt-cu12==0.7.1
31
+ nvidia-nccl-cu12==2.27.5
32
+ nvidia-nvjitlink-cu12==12.8.93
33
+ nvidia-nvshmem-cu12==3.3.20
34
+ nvidia-nvtx-cu12==12.8.90
35
+ opencv-python==4.12.0.88
36
+ opencv-python-headless==4.12.0.88
37
+ packaging==25.0
38
+ pillow==12.1.0
39
+ polars==1.36.1
40
+ polars-runtime-32==1.36.1
41
+ psutil==7.2.1
42
+ pyparsing==3.3.1
43
+ python-dateutil==2.9.0.post0
44
+ PyYAML==6.0.3
45
+ requests==2.32.5
46
+ scipy==1.16.3
47
+ setuptools==80.9.0
48
+ six==1.17.0
49
+ sqlparse==0.5.5
50
+ sympy==1.14.0
51
+ torch==2.9.1
52
+ torchvision==0.24.1
53
+ triton==3.5.1
54
+ typing_extensions==4.15.0
55
+ ultralytics==8.3.246
56
+ ultralytics-thop==2.0.18
57
+ urllib3==2.6.2
satcap_project/__pycache__/settings.cpython-312.pyc ADDED
Binary file (2.5 kB). View file
 
satcap_project/__pycache__/urls.cpython-312.pyc ADDED
Binary file (722 Bytes). View file
 
satcap_project/__pycache__/wsgi.cpython-312.pyc ADDED
Binary file (467 Bytes). View file
 
satcap_project/settings.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from pathlib import Path
3
+
4
+ BASE_DIR = Path(__file__).resolve().parent.parent
5
+
6
+ SECRET_KEY = 'django-insecure-satcap-oceans-secret-key'
7
+
8
+ DEBUG = True
9
+
10
+ ALLOWED_HOSTS = ['*']
11
+
12
+ INSTALLED_APPS = [
13
+ 'django.contrib.admin',
14
+ 'django.contrib.auth',
15
+ 'django.contrib.contenttypes',
16
+ 'django.contrib.sessions',
17
+ 'django.contrib.messages',
18
+ 'django.contrib.staticfiles',
19
+ 'rest_framework',
20
+ 'corsheaders',
21
+ 'api',
22
+ ]
23
+
24
+ MIDDLEWARE = [
25
+ 'corsheaders.middleware.CorsMiddleware',
26
+ 'django.middleware.security.SecurityMiddleware',
27
+ 'django.contrib.sessions.middleware.SessionMiddleware',
28
+ 'django.middleware.common.CommonMiddleware',
29
+ 'django.middleware.csrf.CsrfViewMiddleware',
30
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
31
+ 'django.contrib.messages.middleware.MessageMiddleware',
32
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
33
+ ]
34
+
35
+ ROOT_URLCONF = 'satcap_project.urls'
36
+
37
+ TEMPLATES = [
38
+ {
39
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
40
+ 'DIRS': [],
41
+ 'APP_DIRS': True,
42
+ 'OPTIONS': {
43
+ 'context_processors': [
44
+ 'django.template.context_processors.debug',
45
+ 'django.template.context_processors.request',
46
+ 'django.contrib.auth.context_processors.auth',
47
+ 'django.contrib.messages.context_processors.messages',
48
+ ],
49
+ },
50
+ },
51
+ ]
52
+
53
+ WSGI_APPLICATION = 'satcap_project.wsgi.application'
54
+
55
+ DATABASES = {
56
+ 'default': {
57
+ 'ENGINE': 'django.db.backends.sqlite3',
58
+ 'NAME': BASE_DIR / 'db.sqlite3',
59
+ }
60
+ }
61
+
62
+ AUTH_PASSWORD_VALIDATORS = [
63
+ {
64
+ 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
65
+ },
66
+ {
67
+ 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
68
+ },
69
+ {
70
+ 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
71
+ },
72
+ {
73
+ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
74
+ },
75
+ ]
76
+
77
+ LANGUAGE_CODE = 'en-us'
78
+
79
+ TIME_ZONE = 'UTC'
80
+
81
+ USE_I18N = True
82
+
83
+ USE_TZ = True
84
+
85
+ STATIC_URL = 'static/'
86
+
87
+ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
88
+
89
+ CORS_ALLOW_ALL_ORIGINS = True # For development
90
+
91
+ MEDIA_URL = '/media/'
92
+ MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
satcap_project/urls.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from django.contrib import admin
2
+ from django.urls import path, include
3
+ from django.conf import settings
4
+ from django.conf.urls.static import static
5
+
6
+ urlpatterns = [
7
+ path('admin/', admin.site.urls),
8
+ path('api/', include('api.urls')),
9
+ ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
satcap_project/wsgi.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ import os
2
+ from django.core.wsgi import get_wsgi_application
3
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'satcap_project.settings')
4
+ application = get_wsgi_application()