From ed585e6a569ea58efd77e065373d6c616ad23079 Mon Sep 17 00:00:00 2001
From: pacnpal <183241239+pacnpal@users.noreply.github.com>
Date: Sun, 3 Nov 2024 20:21:39 +0000
Subject: [PATCH] fix commas
---
history_tracking/__init__.py | 2 +
history_tracking/admin.py | 3 +
history_tracking/apps.py | 20 ++++
history_tracking/management/__init__.py | 0
.../management/commands/__init__.py | 0
.../management/commands/initialize_history.py | 99 +++++++++++++++++
history_tracking/migrations/0001_initial.py | 76 +++++++++++++
history_tracking/migrations/__init__.py | 0
history_tracking/mixins.py | 23 ++++
history_tracking/models.py | 17 +++
history_tracking/tests.py | 3 +
history_tracking/views.py | 3 +
parks/__pycache__/models.cpython-312.pyc | Bin 9881 -> 10429 bytes
..._alter_historicalpark_latitude_and_more.py | 80 ++++++++++++++
parks/models.py | 103 +++++++++---------
static/css/tailwind.css | 28 -----
templates/parks/park_detail.html | 17 ++-
templates/parks/partials/park_list.html | 9 +-
templates/rides/ride_detail.html | 4 +-
.../__pycache__/settings.cpython-312.pyc | Bin 5627 -> 5645 bytes
thrillwiki/settings.py | 1 +
21 files changed, 390 insertions(+), 98 deletions(-)
create mode 100644 history_tracking/__init__.py
create mode 100644 history_tracking/admin.py
create mode 100644 history_tracking/apps.py
create mode 100644 history_tracking/management/__init__.py
create mode 100644 history_tracking/management/commands/__init__.py
create mode 100644 history_tracking/management/commands/initialize_history.py
create mode 100644 history_tracking/migrations/0001_initial.py
create mode 100644 history_tracking/migrations/__init__.py
create mode 100644 history_tracking/mixins.py
create mode 100644 history_tracking/models.py
create mode 100644 history_tracking/tests.py
create mode 100644 history_tracking/views.py
create mode 100644 parks/migrations/0006_alter_historicalpark_latitude_and_more.py
diff --git a/history_tracking/__init__.py b/history_tracking/__init__.py
new file mode 100644
index 00000000..946f71a0
--- /dev/null
+++ b/history_tracking/__init__.py
@@ -0,0 +1,2 @@
+# history_tracking/__init__.py
+default_app_config = "history_tracking.apps.HistoryTrackingConfig"
diff --git a/history_tracking/admin.py b/history_tracking/admin.py
new file mode 100644
index 00000000..8c38f3f3
--- /dev/null
+++ b/history_tracking/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/history_tracking/apps.py b/history_tracking/apps.py
new file mode 100644
index 00000000..cf058912
--- /dev/null
+++ b/history_tracking/apps.py
@@ -0,0 +1,20 @@
+# history_tracking/apps.py
+from django.apps import AppConfig
+
+
+class HistoryTrackingConfig(AppConfig):
+ default_auto_field = "django.db.models.BigAutoField"
+ name = "history_tracking"
+
+ def ready(self):
+ from .mixins import HistoricalChangeMixin
+ from .models import Park
+
+ models_with_history = [Park]
+
+ for model in models_with_history:
+ # Check if mixin is already applied
+ if HistoricalChangeMixin not in model.history.model.__bases__:
+ model.history.model.__bases__ = (
+ HistoricalChangeMixin,
+ ) + model.history.model.__bases__
diff --git a/history_tracking/management/__init__.py b/history_tracking/management/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/history_tracking/management/commands/__init__.py b/history_tracking/management/commands/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/history_tracking/management/commands/initialize_history.py b/history_tracking/management/commands/initialize_history.py
new file mode 100644
index 00000000..51bd636f
--- /dev/null
+++ b/history_tracking/management/commands/initialize_history.py
@@ -0,0 +1,99 @@
+# history_tracking/management/commands/initialize_history.py
+from django.core.management.base import BaseCommand
+from django.utils import timezone
+from django.apps import apps
+from django.db.models import Model
+from simple_history.models import HistoricalRecords
+
+
+class Command(BaseCommand):
+ help = "Initialize history records for existing objects with historical records"
+
+ def add_arguments(self, parser):
+ parser.add_argument(
+ "--model",
+ type=str,
+ help="Specify model in format app_name.ModelName (e.g., history_tracking.Park)",
+ )
+ parser.add_argument(
+ "--all",
+ action="store_true",
+ help="Initialize history for all models with historical records",
+ )
+ parser.add_argument(
+ "--force",
+ action="store_true",
+ help="Create history even if records already exist",
+ )
+
+ def initialize_model(self, model, force=False):
+ total = model.objects.count()
+ initialized = 0
+ model_name = f"{model._meta.app_label}.{model._meta.model_name}"
+
+ self.stdout.write(f"Processing {model_name}: Found {total} records")
+
+ for obj in model.objects.all():
+ try:
+ if force or not obj.history.exists():
+ obj.history.create(
+ history_date=timezone.now(),
+ history_type="+",
+ history_change_reason="Initial history record",
+ **{
+ field.name: getattr(obj, field.name)
+ for field in obj._meta.fields
+ if not isinstance(field, HistoricalRecords)
+ },
+ )
+ initialized += 1
+ self.stdout.write(f"Created history for {model_name} id={obj.pk}")
+ except Exception as e:
+ self.stdout.write(
+ self.style.ERROR(
+ f"Error creating history for {model_name} id={obj.pk}: {str(e)}"
+ )
+ )
+
+ return initialized, total
+
+ def handle(self, *args, **options):
+ if not options["model"] and not options["all"]:
+ self.stdout.write(
+ self.style.ERROR("Please specify either --model or --all")
+ )
+ return
+
+ force = options["force"]
+ total_initialized = 0
+ total_records = 0
+
+ if options["model"]:
+ try:
+ app_label, model_name = options["model"].split(".")
+ model = apps.get_model(app_label, model_name)
+ if hasattr(model, "history"):
+ initialized, total = self.initialize_model(model, force)
+ total_initialized += initialized
+ total_records += total
+ else:
+ self.stdout.write(
+ self.style.ERROR(
+ f'Model {options["model"]} does not have historical records'
+ )
+ )
+ except Exception as e:
+ self.stdout.write(self.style.ERROR(str(e)))
+ else:
+ # Process all models with historical records
+ for model in apps.get_models():
+ if hasattr(model, "history"):
+ initialized, total = self.initialize_model(model, force)
+ total_initialized += initialized
+ total_records += total
+
+ self.stdout.write(
+ self.style.SUCCESS(
+ f"Successfully initialized {total_initialized} of {total_records} total records"
+ )
+ )
diff --git a/history_tracking/migrations/0001_initial.py b/history_tracking/migrations/0001_initial.py
new file mode 100644
index 00000000..e8d71312
--- /dev/null
+++ b/history_tracking/migrations/0001_initial.py
@@ -0,0 +1,76 @@
+# Generated by Django 5.1.2 on 2024-11-03 19:59
+
+import django.db.models.deletion
+import history_tracking.mixins
+import simple_history.models
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name="Park",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("name", models.CharField(max_length=200)),
+ ],
+ ),
+ migrations.CreateModel(
+ name="HistoricalPark",
+ fields=[
+ (
+ "id",
+ models.BigIntegerField(
+ auto_created=True, blank=True, db_index=True, verbose_name="ID"
+ ),
+ ),
+ ("name", models.CharField(max_length=200)),
+ ("history_id", models.AutoField(primary_key=True, serialize=False)),
+ ("history_date", models.DateTimeField(db_index=True)),
+ ("history_change_reason", models.CharField(max_length=100, null=True)),
+ (
+ "history_type",
+ models.CharField(
+ choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
+ max_length=1,
+ ),
+ ),
+ (
+ "history_user",
+ models.ForeignKey(
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ related_name="+",
+ to=settings.AUTH_USER_MODEL,
+ ),
+ ),
+ ],
+ options={
+ "verbose_name": "historical park",
+ "verbose_name_plural": "historical parks",
+ "ordering": ("-history_date", "-history_id"),
+ "get_latest_by": ("history_date", "history_id"),
+ },
+ bases=(
+ history_tracking.mixins.HistoricalChangeMixin,
+ simple_history.models.HistoricalChanges,
+ models.Model,
+ ),
+ ),
+ ]
diff --git a/history_tracking/migrations/__init__.py b/history_tracking/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/history_tracking/mixins.py b/history_tracking/mixins.py
new file mode 100644
index 00000000..fd81e158
--- /dev/null
+++ b/history_tracking/mixins.py
@@ -0,0 +1,23 @@
+# history_tracking/mixins.py
+
+
+class HistoricalChangeMixin:
+ @property
+ def diff_against_previous(self):
+ prev_record = self.prev_record
+ if not prev_record:
+ return {}
+
+ changes = {}
+ for field in self.__dict__:
+ if field not in [
+ "history_date",
+ "history_id",
+ "history_type",
+ "history_user_id",
+ ] and not field.startswith("_"):
+ old_value = getattr(prev_record, field)
+ new_value = getattr(self, field)
+ if old_value != new_value:
+ changes[field] = {"old": old_value, "new": new_value}
+ return changes
diff --git a/history_tracking/models.py b/history_tracking/models.py
new file mode 100644
index 00000000..8fc5524b
--- /dev/null
+++ b/history_tracking/models.py
@@ -0,0 +1,17 @@
+# history_tracking/models.py
+from django.db import models
+from simple_history.models import HistoricalRecords
+from .mixins import HistoricalChangeMixin
+
+
+class Park(models.Model):
+ name = models.CharField(max_length=200)
+ # ... other fields ...
+ history = HistoricalRecords()
+
+ @property
+ def _history_model(self):
+ return self.history.model
+
+
+# Apply the mixin
diff --git a/history_tracking/tests.py b/history_tracking/tests.py
new file mode 100644
index 00000000..7ce503c2
--- /dev/null
+++ b/history_tracking/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/history_tracking/views.py b/history_tracking/views.py
new file mode 100644
index 00000000..91ea44a2
--- /dev/null
+++ b/history_tracking/views.py
@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.
diff --git a/parks/__pycache__/models.cpython-312.pyc b/parks/__pycache__/models.cpython-312.pyc
index a575f4dd27167f7107665715dcaf7fae62414852..e2a426ed08dcde68de439aefa557f8a524999f00 100644
GIT binary patch
delta 1170
zcmZXTZD?Cn7{~9qH@VI7c9S&C`zuLPvyS$|O1qY_mZ3vr#
-
- {% if park.city %}{{ park.city }}{% endif %}
- {% if park.city and park.state %}, {% endif %}
- {% if park.state %}{{ park.state }}{% endif %}
- {% if park.country and park.state or park.city %}, {% endif %}
- {% if park.country %}{{ park.country }}{% endif %}
-
+ {% if park.city %}{{ park.city }}{% endif %}{% if park.city and park.state %}, {% endif %}{% if park.state %}{{ park.state }}{% endif %}{% if park.country and park.state or park.city %}, {% endif %}{% if park.country %}{{ park.country }}{% endif %}
+
- {% if park.city %}{{ park.city }}{% endif %}
- {% if park.city and park.state %}, {% endif %}
- {% if park.state %}{{ park.state }}{% endif %}
- {% if park.country and park.state or park.city %}, {% endif %}
- {% if park.country %}{{ park.country }}{% endif %}
+ {% spaceless %}
+ {% if park.city %}{{ park.city }}{% endif %}{% if park.city and park.state %}, {% endif %}{% if park.state %}{{ park.state }}{% endif %}{% if park.country and park.state or park.city %}, {% endif %}{% if park.country %}{{ park.country }}{% endif %}
+ {{ park.name }}
{% if park.city or park.state or park.country %}
-