Expose some timeseries from TimescaleDB over Django

This commit is contained in:
2025-03-13 23:35:05 +01:00
parent 05f7bf582c
commit d8f406d628
5 changed files with 83 additions and 2 deletions

32
ram/ram/db_router.py Normal file
View File

@@ -0,0 +1,32 @@
class TelemetryRouter:
db_table = "telemetry_10secs"
def db_for_read(self, model, **hints):
"""Send read operations to the correct database."""
if model._meta.db_table == self.db_table:
return "telemetry" # Replace with your database name
return None # Default database
def db_for_write(self, model, **hints):
"""Send write operations to the correct database."""
if model._meta.db_table == self.db_table:
return False # Prevent Django from writing RO tables
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the auth or contenttypes apps is
involved.
"""
if (
obj1._meta.db_table == self.db_table
or obj2._meta.db_table == self.db_table
):
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""Prevent Django from migrating this model if it's using a specific database."""
if db == "telemetry":
return False # Prevent Django from creating/modifying tables
return None

View File

@@ -95,8 +95,16 @@ DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": STORAGE_DIR / "db.sqlite3",
}
},
"telemetry": {
"ENGINE": "django.db.backends.postgresql",
"HOST": "127.0.0.1",
"NAME": "dccmonitor",
"USER": "dccmonitor",
"PASSWORD": "dccmonitor",
},
}
DATABASE_ROUTERS = ["ram.db_router.TelemetryRouter"]
# Password validation

View File

@@ -17,6 +17,7 @@ from roster.models import (
RollingStockImage,
RollingStockProperty,
RollingStockJournal,
RollingStockTelemetry,
)
@@ -287,3 +288,29 @@ class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin):
download_csv.short_description = "Download selected items as CSV"
actions = [publish, unpublish, download_csv]
@admin.register(RollingStockTelemetry)
class RollingTelemtryAdmin(admin.ModelAdmin):
list_filter = ("bucket", "cab")
list_display = ("bucket_highres", "cab", "max_speed", "avg_speed")
def bucket_highres(self, obj):
return obj.bucket.strftime("%Y-%m-%d %H:%M:%S")
bucket_highres.admin_order_field = "bucket" # Enable sorting
bucket_highres.short_description = "Bucket" # Column name in admin
def get_changelist_instance(self, request):
changelist = super().get_changelist_instance(request)
changelist.list_display_links = None # Disable links
return changelist
def has_add_permission(self, request):
return False # Disable adding new objects
def has_change_permission(self, request, obj=None):
return False # Disable editing objects
def has_delete_permission(self, request, obj=None):
return False # Disable deleting objects

View File

@@ -224,6 +224,20 @@ class RollingStockJournal(models.Model):
objects = PublicManager()
# trick: this is technically an abstract class
# it is made readonly via db_router and admin to avoid any unwanted change
class RollingStockTelemetry(models.Model):
bucket = models.DateTimeField(primary_key=True, editable=False)
cab = models.PositiveIntegerField(editable=False)
avg_speed = models.FloatField(editable=False)
max_speed = models.PositiveIntegerField(editable=False)
class Meta:
db_table = "telemetry_10secs"
ordering = ["cab", "bucket"]
verbose_name_plural = "Telemetries"
# @receiver(models.signals.post_delete, sender=Cab)
# def post_save_image(sender, instance, *args, **kwargs):
# try: