mirror of
https://github.com/daniviga/django-ram.git
synced 2025-08-04 05:07:50 +02:00
Expose some timeseries from TimescaleDB over Django
This commit is contained in:
32
ram/ram/db_router.py
Normal file
32
ram/ram/db_router.py
Normal 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
|
@@ -95,8 +95,16 @@ DATABASES = {
|
|||||||
"default": {
|
"default": {
|
||||||
"ENGINE": "django.db.backends.sqlite3",
|
"ENGINE": "django.db.backends.sqlite3",
|
||||||
"NAME": STORAGE_DIR / "db.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
|
# Password validation
|
||||||
|
@@ -17,6 +17,7 @@ from roster.models import (
|
|||||||
RollingStockImage,
|
RollingStockImage,
|
||||||
RollingStockProperty,
|
RollingStockProperty,
|
||||||
RollingStockJournal,
|
RollingStockJournal,
|
||||||
|
RollingStockTelemetry,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -287,3 +288,29 @@ class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin):
|
|||||||
|
|
||||||
download_csv.short_description = "Download selected items as CSV"
|
download_csv.short_description = "Download selected items as CSV"
|
||||||
actions = [publish, unpublish, download_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
|
||||||
|
@@ -224,6 +224,20 @@ class RollingStockJournal(models.Model):
|
|||||||
objects = PublicManager()
|
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)
|
# @receiver(models.signals.post_delete, sender=Cab)
|
||||||
# def post_save_image(sender, instance, *args, **kwargs):
|
# def post_save_image(sender, instance, *args, **kwargs):
|
||||||
# try:
|
# try:
|
||||||
|
@@ -8,7 +8,7 @@ django-countries
|
|||||||
django-health-check
|
django-health-check
|
||||||
django-admin-sortable2
|
django-admin-sortable2
|
||||||
django-tinymce
|
django-tinymce
|
||||||
# Optional: # psycopg2-binary
|
psycopg2-binary
|
||||||
# Required by django-countries and not always installed
|
# Required by django-countries and not always installed
|
||||||
# by default on modern venvs (like Python 3.12 on Fedora 39)
|
# by default on modern venvs (like Python 3.12 on Fedora 39)
|
||||||
setuptools
|
setuptools
|
||||||
|
Reference in New Issue
Block a user