From ee001b0256982579b380affb3b7546190ba4c1a7 Mon Sep 17 00:00:00 2001 From: Adam Goldsmith Date: Tue, 19 Sep 2023 01:06:24 -0400 Subject: [PATCH] doorcontrol: Move Door names from HIDEvents into new table --- doorcontrol/admin.py | 11 ++- doorcontrol/migrations/0001_initial.py | 6 ++ ...door_remove_hidevent_door_name_and_more.py | 74 +++++++++++++++++++ doorcontrol/models.py | 14 +++- doorcontrol/routers.py | 4 +- doorcontrol/views.py | 2 +- 6 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 doorcontrol/migrations/0002_door_remove_hidevent_door_name_and_more.py diff --git a/doorcontrol/admin.py b/doorcontrol/admin.py index 0470e10..8dbd58f 100644 --- a/doorcontrol/admin.py +++ b/doorcontrol/admin.py @@ -1,6 +1,11 @@ from django.contrib import admin -from .models import HIDEvent +from .models import Door, HIDEvent + + +@admin.register(Door) +class DoorAdmin(admin.ModelAdmin): + pass class IsRedFilter(admin.SimpleListFilter): @@ -23,10 +28,10 @@ class IsRedFilter(admin.SimpleListFilter): @admin.register(HIDEvent) class HIDEventAdmin(admin.ModelAdmin): search_fields = ["forename", "surname", "cardholder_id"] - list_display = ["door_name", "timestamp", "event_type", "description", "is_red"] + list_display = ["timestamp", "door", "event_type", "description", "is_red"] list_filter = [ "timestamp", - "door_name", + "door", "event_type", IsRedFilter, ] diff --git a/doorcontrol/migrations/0001_initial.py b/doorcontrol/migrations/0001_initial.py index 12e5f76..aa5449c 100644 --- a/doorcontrol/migrations/0001_initial.py +++ b/doorcontrol/migrations/0001_initial.py @@ -95,4 +95,10 @@ class Migration(migrations.Migration): "managed": False, }, ), + migrations.AddConstraint( + model_name="hidevent", + constraint=models.UniqueConstraint( + fields=("door_name", "timestamp", "event_type"), name="unique_hidevent" + ), + ), ] diff --git a/doorcontrol/migrations/0002_door_remove_hidevent_door_name_and_more.py b/doorcontrol/migrations/0002_door_remove_hidevent_door_name_and_more.py new file mode 100644 index 0000000..db9fba2 --- /dev/null +++ b/doorcontrol/migrations/0002_door_remove_hidevent_door_name_and_more.py @@ -0,0 +1,74 @@ +# Generated by Django 4.2.5 on 2023-09-19 04:20 + +from django.db import migrations, models +import django.db.models.deletion + + +def link_events_to_doors(apps, schema_editor): + HIDEvent = apps.get_model("doorcontrol", "HIDEvent") + Door = apps.get_model("doorcontrol", "Door") + for event in HIDEvent.objects.all(): + door, created = Door.objects.get_or_create(name=event.door_name) + event.door = door + event.save() + + +class Migration(migrations.Migration): + dependencies = [ + ("doorcontrol", "0001_initial"), + ] + + operations = [ + migrations.AlterModelOptions( + name="hidevent", + options={"ordering": ("-timestamp",)}, + ), + migrations.CreateModel( + name="Door", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=64, unique=True)), + ], + ), + # create nullable foreign key to door + migrations.AddField( + model_name="hidevent", + name="door", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="doorcontrol.door", + null=True, + ), + ), + # create new Doors and link them to HID Events + migrations.RunPython(link_events_to_doors, atomic=True), + # make door foreign key not nullable + migrations.AlterField( + model_name="hidevent", + name="door", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="doorcontrol.door" + ), + ), + # remove old constaint + migrations.RemoveConstraint(model_name="hidevent", name="unique_hidevent"), + # remove old name field + migrations.RemoveField( + model_name="hidevent", + name="door_name", + ), + migrations.AddConstraint( + model_name="hidevent", + constraint=models.UniqueConstraint( + fields=("door", "timestamp", "event_type"), name="unique_hidevent" + ), + ), + ] diff --git a/doorcontrol/models.py b/doorcontrol/models.py index 79b36ca..adaa318 100644 --- a/doorcontrol/models.py +++ b/doorcontrol/models.py @@ -3,6 +3,13 @@ from django.db.models import ExpressionWrapper, F, Func, Q from django.db.models.functions import Mod +class Door(models.Model): + name = models.CharField(max_length=64, unique=True) + + def __str__(self): + return self.name + + class HIDEventQuerySet(models.QuerySet): def with_is_red(self): """Based on `function isRedEvent` from /html/hid-global.js on a HID EDGE EVO Solo""" @@ -98,7 +105,7 @@ class HIDEvent(models.Model): DOOR_UNLOCKED = 12032, "Door Unlocked" DOOR_LOCKED = 12033, "Door Locked" - door_name = models.CharField(max_length=64, db_column="doorName") + door = models.ForeignKey(Door, on_delete=models.CASCADE) timestamp = models.DateTimeField() event_type = models.IntegerField(db_column="eventType", choices=EventType.choices) reader_address = models.IntegerField(db_column="readerAddress") @@ -156,7 +163,7 @@ class HIDEvent(models.Model): return event_types.get(self.event_type, f"Unknown Event Type {self.event_type}") def __str__(self): - return f"{self.door_name} {self.timestamp} - {self.description}" + return f"{self.door.name} {self.timestamp} - {self.description}" def decoded_card_number(self) -> str: """Requires annotations from `with_decoded_card_number`""" @@ -173,9 +180,8 @@ class HIDEvent(models.Model): class Meta: constraints = [ models.UniqueConstraint( - fields=["door_name", "timestamp", "event_type"], name="unique_hidevent" + fields=["door", "timestamp", "event_type"], name="unique_hidevent" ) ] - managed = False db_table = "hidevent" ordering = ("-timestamp",) diff --git a/doorcontrol/routers.py b/doorcontrol/routers.py index ddfc41a..dc7ccdc 100644 --- a/doorcontrol/routers.py +++ b/doorcontrol/routers.py @@ -13,8 +13,8 @@ class DoorControlRouter: return None def allow_migrate(self, db, app_label, model_name=None, **hints): - if db == self.db: - return False + if app_label == self.app_label: + return db == self.db return None def allow_relation(self, obj1, obj2, **hints): diff --git a/doorcontrol/views.py b/doorcontrol/views.py index 4900716..4268fc8 100644 --- a/doorcontrol/views.py +++ b/doorcontrol/views.py @@ -163,7 +163,7 @@ class DeniedAccess(BaseAccessReport): return [ { "timestamp": event.timestamp, - "door name": event.door_name, + "door name": event.door.name, "event type": HIDEvent.EventType(event.event_type).label, "name": " ".join( (n for n in [event.forename, event.surname] if n is not None)