mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-22 03:51:08 -05:00
fix commas
This commit is contained in:
2
history_tracking/__init__.py
Normal file
2
history_tracking/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# history_tracking/__init__.py
|
||||
default_app_config = "history_tracking.apps.HistoryTrackingConfig"
|
||||
3
history_tracking/admin.py
Normal file
3
history_tracking/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
20
history_tracking/apps.py
Normal file
20
history_tracking/apps.py
Normal file
@@ -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__
|
||||
0
history_tracking/management/__init__.py
Normal file
0
history_tracking/management/__init__.py
Normal file
0
history_tracking/management/commands/__init__.py
Normal file
0
history_tracking/management/commands/__init__.py
Normal file
99
history_tracking/management/commands/initialize_history.py
Normal file
99
history_tracking/management/commands/initialize_history.py
Normal file
@@ -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"
|
||||
)
|
||||
)
|
||||
76
history_tracking/migrations/0001_initial.py
Normal file
76
history_tracking/migrations/0001_initial.py
Normal file
@@ -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,
|
||||
),
|
||||
),
|
||||
]
|
||||
0
history_tracking/migrations/__init__.py
Normal file
0
history_tracking/migrations/__init__.py
Normal file
23
history_tracking/mixins.py
Normal file
23
history_tracking/mixins.py
Normal file
@@ -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
|
||||
17
history_tracking/models.py
Normal file
17
history_tracking/models.py
Normal file
@@ -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
|
||||
3
history_tracking/tests.py
Normal file
3
history_tracking/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
3
history_tracking/views.py
Normal file
3
history_tracking/views.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
Reference in New Issue
Block a user