Skip to content

Commit

Permalink
Fix one-to-one relations with historical models, correctly handle rel…
Browse files Browse the repository at this point in the history
…ated deletes
  • Loading branch information
macro1 committed Apr 22, 2015
1 parent 601592a commit a8dae12
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Changes
tip (unreleased)
----------------
- Fix OneToOneField transformation for historical models (gh-166)
- Disable cascading deletes from related models to historical models
- Fix restoring historical instances with missing one-to-one relations (gh-162)

1.6.0 (2015-04-16)
------------------
Expand Down
4 changes: 3 additions & 1 deletion simple_history/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ def copy_fields(self, model):
db_index=True,
serialize=True,
unique=False,
on_delete=models.DO_NOTHING,
**field_arguments
)
field.name = old_field.name
Expand All @@ -173,7 +174,8 @@ def revert_url(self):
[getattr(self, opts.pk.attname), self.history_id])

def get_instance(self):
return model(**dict([(k, getattr(self, k)) for k in fields]))
return model(**{field.attname: getattr(self, field.attname)
for field in fields.values()})

return {
'history_id': models.AutoField(primary_key=True),
Expand Down
5 changes: 5 additions & 0 deletions simple_history/tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,8 @@ class UserAccessorDefault(models.Model):

class UserAccessorOverride(models.Model):
pass


class Employee(models.Model):
manager = models.OneToOneField('Employee', null=True)
history = HistoricalRecords()
25 changes: 24 additions & 1 deletion simple_history/tests/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
AbstractBase, ConcreteAttr, ConcreteUtil, SelfFK, Temperature, WaterLevel,
ExternalModel1, ExternalModel3, UnicodeVerboseName, HistoricalChoice,
HistoricalState, HistoricalCustomFKError, Series, SeriesWork, PollInfo,
UserAccessorDefault, UserAccessorOverride
UserAccessorDefault, UserAccessorOverride, Employee
)
from ..external.models import ExternalModel2, ExternalModel4

Expand Down Expand Up @@ -706,3 +706,26 @@ def test_accessor_default(self):
def test_accessor_override(self):
register(UserAccessorOverride, user_related_name='my_history_model_accessor')
assert hasattr(User, 'my_history_model_accessor')


class TestMissingOneToOne(TestCase):

def setUp(self):
self.manager1 = Employee.objects.create()
self.manager2 = Employee.objects.create()
self.employee = Employee.objects.create(manager=self.manager1)
self.employee.manager = self.manager2
self.employee.save()
self.manager1.delete()

def test_history_is_complete(self):
historical_manager_ids = list(self.employee.history.order_by('pk')
.values_list('manager_id', flat=True))
self.assertEqual(historical_manager_ids, [1, 2])

def test_restore_employee(self):
historical = self.employee.history.order_by('pk')[0]
original = historical.instance
self.assertEqual(original.manager_id, 1)
with self.assertRaises(Employee.DoesNotExist):
original.manager

0 comments on commit a8dae12

Please sign in to comment.