Skip to content

Commit f3de643

Browse files
committed
Support for custom tables names
Currently, the history table name is hardcoded (APP_historicalMODEL). This pull request add support for custom tables names by adding a `db_history_table` option. As Django reject all unknown option in `Meta` inner class, I've added an `History` inner class to store this option (and possibly others future options). ``` class Organization(models.Model): name = models.CharField(_('Organization or Name'), max_length=25) address = models.CharField(_('Address'), max_length=250) zipcode = models.CharField(_('Postal code'), max_length=10, null=True) city = models.CharField(_('City'), max_length=50) country = models.CharField(_('Country'), max_length=2, \ choices=COUNTRIES_CHOICES) def __str__(self): return self.name class History: db_history_table = 'organizations_history' class Meta: db_table = 'organizations' ``` TODO: Documentation.
1 parent 089c5d4 commit f3de643

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

simple_history/models.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ def create_history_model(self, model):
117117
attrs.update(self.get_extra_fields(model, fields))
118118
# type in python2 wants str as a first argument
119119
attrs.update(Meta=type(str('Meta'), (), self.get_meta_options(model)))
120+
history_options = self.get_history_options(model)
121+
if 'db_history_table' in history_options:
122+
attrs['Meta'].db_table = history_options['db_history_table']
120123
name = 'Historical%s' % model._meta.object_name
121124
registered_models[model._meta.db_table] = model
122125
return python_2_unicode_compatible(
@@ -225,6 +228,27 @@ def get_meta_options(self, model):
225228
meta_fields['verbose_name'] = name
226229
return meta_fields
227230

231+
def get_history_options(self, model):
232+
"""
233+
Returns a dictionary of options set to the History inner
234+
class of the historical record model.
235+
"""
236+
VALID_OPTIONS = ['db_history_table']
237+
if hasattr(model, 'History'):
238+
history_options = model.History.__dict__.copy()
239+
for key in model.History.__dict__:
240+
# Ignore any private attributes that we doesn't care about, like
241+
# "__module__" or "__dict__".
242+
# NOTE: We can't modify a dictionary's contents while looping
243+
# over it, so we loop over the *original* dictionary instead.
244+
if key.startswith('_'):
245+
del history_options[key]
246+
for option in history_options:
247+
if not option in VALID_OPTIONS:
248+
raise TypeError("'class History' got invalid attribute: %s" % (option,))
249+
return history_options
250+
return {}
251+
228252
def post_save(self, instance, created, **kwargs):
229253
if not created and hasattr(instance, 'skip_history_when_saving'):
230254
return

simple_history/tests/models.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,11 @@ class Province(models.Model):
264264
class City(models.Model):
265265
country = models.ForeignKey(Country, db_column='countryCode')
266266
history = HistoricalRecords()
267+
268+
class Contact(models.Model):
269+
name = models.CharField(max_length=30)
270+
email = models.EmailField(max_length=255, unique=True)
271+
history = HistoricalRecords()
272+
273+
class History:
274+
db_history_table = 'contacts_history'

simple_history/tests/tests/test_models.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
ExternalModel1, ExternalModel3, UnicodeVerboseName, HistoricalChoice,
2020
HistoricalState, HistoricalCustomFKError, Series, SeriesWork, PollInfo,
2121
UserAccessorDefault, UserAccessorOverride, Employee, Country, Province,
22-
City
22+
City, Contact
2323
)
2424
from ..external.models import ExternalModel2, ExternalModel4
2525

@@ -745,3 +745,10 @@ def test_restore_employee(self):
745745
self.assertEqual(original.manager_id, 1)
746746
with self.assertRaises(Employee.DoesNotExist):
747747
original.manager
748+
749+
class CustomTableNameTest(TestCase):
750+
def get_table_name(self, manager):
751+
return manager.model._meta.db_table
752+
753+
def test_custom_table_name(self):
754+
self.assertEqual(self.get_table_name(Contact.history), 'contacts_history')

0 commit comments

Comments
 (0)