1
1
import uuid_extensions
2
+ from django .apps import apps
2
3
from django .db import models
3
- from simple_history .models import HistoricalRecords
4
+ from simple_history .models import HistoricalRecords , registered_models
4
5
5
6
6
7
def _history_user_getter (historical_instance ):
@@ -17,8 +18,61 @@ def _history_user_setter(historical_instance, user):
17
18
historical_instance .history_user_id = user
18
19
19
20
21
+ class ProxyAwareHistoricalRecords (HistoricalRecords ):
22
+ """Historical records with shared history for proxy models.
23
+
24
+ This is a workaround for https://github.com/jazzband/django-simple-history/issues/544.
25
+
26
+ Copied from https://github.com/jazzband/django-simple-history/issues/544#issuecomment-1538615799
27
+ """
28
+
29
+ def _find_base_history (self , opts ):
30
+ base_history = None
31
+ for parent_class in opts .parents .keys ():
32
+ if hasattr (parent_class , "history" ):
33
+ base_history = parent_class .history .model
34
+ return base_history
35
+
36
+ def create_history_model (self , model , inherited ):
37
+ opts = model ._meta
38
+ if opts .proxy :
39
+ base_history = self ._find_base_history (opts )
40
+ if base_history :
41
+ return self .create_proxy_history_model (model , inherited , base_history )
42
+
43
+ return super ().create_history_model (model , inherited )
44
+
45
+ def create_proxy_history_model (self , model , inherited , base_history ):
46
+ opts = model ._meta
47
+ attrs = {
48
+ "__module__" : self .module ,
49
+ "_history_excluded_fields" : self .excluded_fields ,
50
+ }
51
+ app_module = f"{ opts .app_label } .models"
52
+ if inherited :
53
+ attrs ["__module__" ] = model .__module__
54
+ elif model .__module__ != self .module : # pragma: no cover
55
+ # registered under different app
56
+ attrs ["__module__" ] = self .module
57
+ elif app_module != self .module : # pragma: no cover
58
+ # Abuse an internal API because the app registry is loading.
59
+ app = apps .app_configs [opts .app_label ]
60
+ models_module = app .name
61
+ attrs ["__module__" ] = models_module
62
+
63
+ attrs .update (
64
+ Meta = type ("Meta" , (), {** self .get_meta_options (model ), "proxy" : True })
65
+ )
66
+ if self .table_name is not None : # pragma: no cover
67
+ attrs ["Meta" ].db_table = self .table_name
68
+
69
+ name = self .get_history_model_name (model )
70
+ registered_models [opts .db_table ] = model
71
+ return type (str (name ), (base_history ,), attrs )
72
+
73
+
20
74
class HistoricalModel (models .Model ):
21
- history = HistoricalRecords (
75
+ history = ProxyAwareHistoricalRecords (
22
76
inherit = True ,
23
77
history_user_id_field = models .CharField (null = True , max_length = 150 ),
24
78
history_user_setter = _history_user_setter ,
0 commit comments