Skip to content

Commit 2e89360

Browse files
author
Ross Mechanic
authored
GH-512: allow foreign key to reference self using self str (#513)
* GH-512: Fix bug that disallowed using 'self' str when creating ForeignKey to self * Formatted * Updated CHANGES.rst * last change * Fixed missing on_delete
1 parent 45d6f8e commit 2e89360

File tree

4 files changed

+36
-3
lines changed

4 files changed

+36
-3
lines changed

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Unreleased
66
- Add support for `using` chained manager method and save/delete keyword argument (gh-507)
77
- Added management command `clean_duplicate_history` to remove duplicate history entries (gh-483)
88
- Updated most_recent to work with excluded_fields (gh-477)
9+
- Fixed bug that prevented self-referential foreign key from using `'self'` (gh-513)
910

1011
2.6.0 (2018-12-12)
1112
------------------

simple_history/models.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,13 @@ def copy_fields(self, model):
213213
else:
214214
FieldType = type(old_field)
215215

216+
# If field_args['to'] is 'self' then we have a case where the object
217+
# has a foreign key to itself. If we pass the historical record's
218+
# field to = 'self', the foreign key will point to an historical
219+
# record rather than the base record. We can use old_field.model here.
220+
if field_args.get("to", None) == "self":
221+
field_args["to"] = old_field.model
222+
216223
# Override certain arguments passed when creating the field
217224
# so that they work for the historical field.
218225
field_args.update(

simple_history/tests/models.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,3 +553,13 @@ class CustomNameModel(models.Model):
553553
class CustomManagerNameModel(models.Model):
554554
name = models.CharField(max_length=15)
555555
log = HistoricalRecords()
556+
557+
558+
class ForeignKeyToSelfModel(models.Model):
559+
fk_to_self = models.ForeignKey(
560+
"ForeignKeyToSelfModel", null=True, related_name="+", on_delete=models.CASCADE
561+
)
562+
fk_to_self_using_str = models.ForeignKey(
563+
"self", null=True, related_name="+", on_delete=models.CASCADE
564+
)
565+
history = HistoricalRecords()

simple_history/tests/tests/test_models.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import unicode_literals
22

33
import unittest
4+
45
import uuid
56
import warnings
67
from datetime import datetime, timedelta
@@ -43,6 +44,7 @@
4344
ExternalModel1,
4445
ExternalModel3,
4546
FileModel,
47+
ForeignKeyToSelfModel,
4648
HistoricalChoice,
4749
HistoricalCustomFKError,
4850
HistoricalPoll,
@@ -583,7 +585,6 @@ def setUp(self):
583585
self.poll.save()
584586

585587
def test_get_prev_record(self):
586-
587588
self.poll.question = "ask questions?"
588589
self.poll.save()
589590
self.poll.question = "eh?"
@@ -1203,7 +1204,6 @@ def test_signal_is_able_to_retrieve_request_from_thread(self):
12031204

12041205
class WarningOnAbstractModelWithInheritFalseTest(TestCase):
12051206
def test_warning_on_abstract_model_with_inherit_false(self):
1206-
12071207
with warnings.catch_warnings(record=True) as w:
12081208

12091209
class AbstractModelWithInheritFalse(models.Model):
@@ -1224,7 +1224,6 @@ class Meta:
12241224

12251225

12261226
class MultiDBWithUsingTest(TestCase):
1227-
12281227
"""Asserts historical manager respects `using()` and the `using`
12291228
keyword argument in `save()`.
12301229
"""
@@ -1309,3 +1308,19 @@ def test_multidb_with_using_keyword_in_save_and_delete(self):
13091308
.order_by("history_date")
13101309
],
13111310
)
1311+
1312+
1313+
class ForeignKeyToSelfTest(TestCase):
1314+
def setUp(self):
1315+
self.model = ForeignKeyToSelfModel
1316+
self.history_model = self.model.history.model
1317+
1318+
def test_foreign_key_to_self_using_model_str(self):
1319+
self.assertEqual(
1320+
self.model, self.history_model.fk_to_self.field.remote_field.model
1321+
)
1322+
1323+
def test_foreign_key_to_self_using_self_str(self):
1324+
self.assertEqual(
1325+
self.model, self.history_model.fk_to_self_using_str.field.remote_field.model
1326+
)

0 commit comments

Comments
 (0)