Skip to content

Commit 6d7eaf0

Browse files
authored
Add setting to convert FileField to CharField instead of TextField (#625)
1 parent 5750774 commit 6d7eaf0

File tree

6 files changed

+47
-1
lines changed

6 files changed

+47
-1
lines changed

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Authors
4242
- Guillermo Eijo (`guilleijo <https://github.com/guilleijo>`_)
4343
- Hamish Downer
4444
- Hanyin Zhang
45+
- Jack Cushman (`jcushman <https://github.com/jcushman>`_)
4546
- James Muranga (`jamesmura <https://github.com/jamesmura>`_)
4647
- James Pulec
4748
- Jesse Shapiro

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Changes
44
Unreleased
55
----------
66
- Add simple filtering if provided a minutes argument in `clean_duplicate_history` (gh-606)
7+
- Add setting to convert `FileField` to `CharField` instead of `TextField` (gh-623)
78

89
2.8.0 (2019-12-02)
910
------------------

docs/historical_model.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,3 +386,16 @@ or the record invocation: ``app="SomeAppName"``.
386386
register(Opinion, app="SomeAppName")
387387
388388
389+
`FileField` as a `CharField`
390+
----------------------------
391+
392+
By default a ``FileField`` in the base model becomes a ``TextField`` in the history model.
393+
This is a historical choice that django-simple-history preserves for backwards
394+
compatibility; it is more correct for a ``FileField`` to be converted to a
395+
``CharField`` instead. To opt into the new behavior, set the following line in your
396+
``settings.py`` file:
397+
398+
.. code-block:: python
399+
400+
SIMPLE_HISTORY_FILEFIELD_TO_CHARFIELD = True
401+

simple_history/models.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,10 @@ def transform_field(field):
545545

546546
elif isinstance(field, models.FileField):
547547
# Don't copy file, just path.
548-
field.__class__ = models.TextField
548+
if getattr(settings, "SIMPLE_HISTORY_FILEFIELD_TO_CHARFIELD", False):
549+
field.__class__ = models.CharField
550+
else:
551+
field.__class__ = models.TextField
549552

550553
# Historical instance shouldn't change create/update timestamps
551554
field.auto_now = False

simple_history/tests/models.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,20 @@ class FileModel(models.Model):
192192
history = HistoricalRecords()
193193

194194

195+
# Set SIMPLE_HISTORY_FILEFIELD_TO_CHARFIELD
196+
setattr(settings, "SIMPLE_HISTORY_FILEFIELD_TO_CHARFIELD", True)
197+
198+
199+
class CharFieldFileModel(models.Model):
200+
title = models.CharField(max_length=100)
201+
file = models.FileField(upload_to="files")
202+
history = HistoricalRecords()
203+
204+
205+
# Clear SIMPLE_HISTORY_FILEFIELD_TO_CHARFIELD
206+
delattr(settings, "SIMPLE_HISTORY_FILEFIELD_TO_CHARFIELD")
207+
208+
195209
class Document(models.Model):
196210
changed_by = models.ForeignKey(
197211
User, on_delete=models.CASCADE, null=True, blank=True

simple_history/tests/tests/test_models.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
BucketDataRegisterChangedBy,
4343
BucketMember,
4444
CharFieldChangeReasonModel,
45+
CharFieldFileModel,
4546
Choice,
4647
City,
4748
ConcreteAttr,
@@ -316,6 +317,19 @@ def test_file_field(self):
316317
self.assertEqual(create_record.file, "files/name")
317318
self.assertEqual(update_record.file, "")
318319

320+
def test_file_field_with_char_field_setting(self):
321+
# setting means history table's file field is a CharField
322+
file_field = CharFieldFileModel.history.model._meta.get_field("file")
323+
self.assertIs(type(file_field), models.CharField)
324+
self.assertEqual(file_field.max_length, 100)
325+
# file field works the same as test_file_field()
326+
model = CharFieldFileModel.objects.create(file=get_fake_file("name"))
327+
self.assertEqual(model.file.name, "files/name")
328+
model.file.delete()
329+
update_record, create_record = model.history.all()
330+
self.assertEqual(create_record.file, "files/name")
331+
self.assertEqual(update_record.file, "")
332+
319333
def test_inheritance(self):
320334
pizza_place = Restaurant.objects.create(name="Pizza Place", rating=3)
321335
pizza_place.rating = 4

0 commit comments

Comments
 (0)