Skip to content

Commit ba5c75d

Browse files
committed
Merge pull request #160 from treyhunner/django18
Add Django 1.8 support
2 parents 38792a7 + 48b4e80 commit ba5c75d

File tree

8 files changed

+71
-46
lines changed

8 files changed

+71
-46
lines changed

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ env:
1010
- DJANGO="Django>=1.4,<1.5"
1111
- DJANGO="Django>=1.6,<1.7"
1212
- DJANGO="Django>=1.7,<1.8"
13+
- DJANGO="Django>=1.8,<1.9"
1314

1415
install:
1516
- pip install -U coverage coveralls $DJANGO
@@ -23,6 +24,8 @@ matrix:
2324
env: DJANGO="Django>=1.6,<1.7"
2425
- python: 2.6
2526
env: DJANGO="Django>=1.7,<1.8"
27+
- python: 2.6
28+
env: DJANGO="Django>=1.8,<1.9"
2629
- python: 3.2
2730
env: DJANGO="Django>=1.4,<1.5"
2831
- python: 3.3
@@ -31,5 +34,7 @@ matrix:
3134
include:
3235
- python: 3.4
3336
env: DJANGO="Django>=1.7,<1.8"
37+
- python: 3.4
38+
env: DJANGO="Django>=1.8,<1.9"
3439

3540
after_success: coveralls

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Authors
2121
- Mauricio de Abreu Antunes
2222
- Micah Denbraver
2323
- Rajesh Pappula
24+
- Rod Xavier Bondoc
2425
- Ross Lote
2526
- Steven Klass
2627
- Trey Hunner

CHANGES.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
Changes
22
=======
33

4+
tip (unreleased)
5+
----------------
6+
- Add support for Django 1.8+
7+
- Deprecated use of ``CustomForeignKeyField`` (to be removed)
8+
49
1.5.4 (2015-01-03)
510
------------------
611
- Fix a bug when models have a ``ForeignKey`` with ``primary_key=True``

simple_history/models.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,33 @@
22

33
import threading
44
import copy
5-
try:
6-
from django.apps import apps
7-
except ImportError: # Django < 1.7
8-
apps = None
5+
import warnings
6+
97
from django.db import models, router
108
from django.db.models import loading
119
from django.db.models.fields.proxy import OrderWrt
1210
from django.db.models.fields.related import RelatedField
13-
from django.db.models.related import RelatedObject
1411
from django.conf import settings
1512
from django.contrib import admin
1613
from django.utils import importlib, six
1714
from django.utils.encoding import python_2_unicode_compatible
1815
from django.utils.encoding import smart_text
1916
from django.utils.timezone import now
2017
from django.utils.translation import string_concat
18+
19+
from .manager import HistoryDescriptor
20+
21+
try:
22+
from django.apps import apps
23+
except ImportError: # Django < 1.7
24+
apps = None
2125
try:
2226
from south.modelsinspector import add_introspection_rules
2327
except ImportError: # south not present
2428
pass
2529
else: # south configuration for CustomForeignKeyField
2630
add_introspection_rules(
2731
[], ["^simple_history.models.CustomForeignKeyField"])
28-
from .manager import HistoryDescriptor
2932

3033
registered_models = {}
3134

@@ -121,18 +124,25 @@ def copy_fields(self, model):
121124
for field in model._meta.fields:
122125
field = copy.copy(field)
123126
field.rel = copy.copy(field.rel)
124-
if isinstance(field, models.ForeignKey):
125-
# Don't allow reverse relations.
126-
# ForeignKey knows best what datatype to use for the column
127-
# we'll used that as soon as it's finalized by copying rel.to
128-
field.__class__ = CustomForeignKeyField
129-
field.rel.related_name = '+'
130-
field.null = True
131-
field.blank = True
132127
if isinstance(field, OrderWrt):
133128
# OrderWrt is a proxy field, switch to a plain IntegerField
134129
field.__class__ = models.IntegerField
135-
transform_field(field)
130+
if isinstance(field, models.ForeignKey):
131+
old_field = field
132+
field = type(field)(
133+
field.rel.to,
134+
related_name='+',
135+
null=True,
136+
blank=True,
137+
primary_key=False,
138+
db_index=True,
139+
serialize=True,
140+
)
141+
field._unique = False
142+
field.name = old_field.name
143+
field.db_constraint = False
144+
else:
145+
transform_field(field)
136146
fields[field.name] = field
137147
return fields
138148

@@ -227,6 +237,8 @@ def get_history_user(self, instance):
227237
class CustomForeignKeyField(models.ForeignKey):
228238

229239
def __init__(self, *args, **kwargs):
240+
warnings.warn("CustomForeignKeyField is deprecated.",
241+
DeprecationWarning)
230242
super(CustomForeignKeyField, self).__init__(*args, **kwargs)
231243
self.db_constraint = False
232244
self.generate_reverse_relation = False
@@ -289,13 +301,6 @@ def get_field(self, other, cls):
289301

290302
def do_related_class(self, other, cls):
291303
field = self.get_field(other, cls)
292-
if not hasattr(self, 'related'):
293-
try:
294-
instance_type = cls.instance_type
295-
except AttributeError: # when model is reconstituted for migration
296-
pass # happens during migrations
297-
else:
298-
self.related = RelatedObject(other, instance_type, self)
299304
transform_field(field)
300305
field.rel = None
301306

simple_history/tests/migration_test_app/migrations/0001_initial.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from __future__ import unicode_literals
44

55
from django.db import models, migrations
6-
import simple_history.models
6+
import django.db.models.deletion
77
from django.conf import settings
88

99

@@ -30,12 +30,9 @@ class Migration(migrations.Migration):
3030
('history_id', models.AutoField(serialize=False, primary_key=True)),
3131
('history_date', models.DateTimeField()),
3232
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
33-
('history_user', models.ForeignKey(null=True, to=settings.AUTH_USER_MODEL)),
33+
('history_user', models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, null=True)),
3434
],
35-
options={
36-
'verbose_name': 'historical yar',
37-
'ordering': ('-history_date', '-history_id'),
38-
},
35+
options={'ordering': ('-history_date', '-history_id'), 'get_latest_by': 'history_date', 'verbose_name': 'historical yar'},
3936
bases=(models.Model,),
4037
),
4138
migrations.CreateModel(
@@ -59,8 +56,8 @@ class Migration(migrations.Migration):
5956
),
6057
migrations.AddField(
6158
model_name='historicalyar',
62-
name='what_id',
63-
field=simple_history.models.CustomForeignKeyField(to='migration_test_app.WhatIMean', blank=True, null=True, related_name='+'),
59+
name='what',
60+
field=models.ForeignKey(related_name='+', db_constraint=False, blank=True, to='migration_test_app.WhatIMean', null=True),
6461
preserve_default=True,
6562
),
6663
]

simple_history/tests/tests/test_admin.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,3 @@ def test_deleteting_user(self):
234234

235235
historical_poll = poll.history.all()[0]
236236
self.assertEqual(historical_poll.history_user, None)
237-

simple_history/tests/tests/test_models.py

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
from __future__ import unicode_literals
22

33
from datetime import datetime, timedelta
4-
try:
5-
from unittest import skipUnless
6-
except ImportError:
7-
from unittest2 import skipUnless
4+
import unittest
85

96
import django
10-
try:
11-
from django.contrib.auth import get_user_model
12-
User = get_user_model()
13-
except ImportError: # django 1.4 compatibility
14-
from django.contrib.auth.models import User
157
from django.db import models
168
from django.db.models.loading import get_model
179
from django.db.models.fields.proxy import OrderWrt
@@ -29,6 +21,16 @@
2921
)
3022
from ..external.models import ExternalModel2, ExternalModel4
3123

24+
try:
25+
from unittest import skipUnless
26+
except ImportError:
27+
from unittest2 import skipUnless
28+
try:
29+
from django.contrib.auth import get_user_model
30+
User = get_user_model()
31+
except ImportError: # django 1.4 compatibility
32+
from django.contrib.auth.models import User
33+
3234
today = datetime(2021, 1, 1, 10, 0)
3335
tomorrow = today + timedelta(days=1)
3436
yesterday = today - timedelta(days=1)
@@ -324,7 +326,7 @@ def test_register_custome_records(self):
324326
self.assertEqual(expected, str(voter.history.all()[0])[:len(expected)])
325327

326328

327-
class CreateHistoryModelTests(TestCase):
329+
class CreateHistoryModelTests(unittest.TestCase):
328330

329331
def test_create_history_model_with_one_to_one_field_to_integer_field(self):
330332
records = HistoricalRecords()
@@ -487,12 +489,20 @@ def test_invalid_bases(self):
487489
self.assertRaises(TypeError, HistoricalRecords, bases=bases)
488490

489491
def test_import_related(self):
490-
field_object = HistoricalChoice._meta.get_field_by_name('poll_id')[0]
491-
self.assertEqual(field_object.related.model, Choice)
492+
field_object = HistoricalChoice._meta.get_field_by_name('poll')[0]
493+
try:
494+
related_model = field_object.rel.related_model
495+
except AttributeError: # Django<1.8
496+
related_model = field_object.related.model
497+
self.assertEqual(related_model, HistoricalChoice)
492498

493499
def test_string_related(self):
494-
field_object = HistoricalState._meta.get_field_by_name('library_id')[0]
495-
self.assertEqual(field_object.related.model, State)
500+
field_object = HistoricalState._meta.get_field_by_name('library')[0]
501+
try:
502+
related_model = field_object.rel.related_model
503+
except AttributeError: # Django<1.8
504+
related_model = field_object.related.model
505+
self.assertEqual(related_model, HistoricalState)
496506

497507
@skipUnless(django.get_version() >= "1.7", "Requires 1.7 migrations")
498508
def test_state_serialization_of_customfk(self):
@@ -652,7 +662,8 @@ class TestLatest(TestCase):
652662
""""Test behavior of `latest()` without any field parameters"""
653663

654664
def setUp(self):
655-
poll = Poll.objects.create(question="Does `latest()` work?", pub_date=yesterday)
665+
poll = Poll.objects.create(
666+
question="Does `latest()` work?", pub_date=yesterday)
656667
poll.pub_date = today
657668
poll.save()
658669

tox.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ envlist =
33
py{26,27}-django14,
44
py{26,27,32,33}-django16,
55
py{27,32,33,34}-django17,
6+
py{27,32,33,34}-django18,
67
py{27,32,33,34}-djangotrunk,
78
docs, flake8
89

@@ -32,5 +33,6 @@ deps =
3233
django14: Django>=1.4,<1.5
3334
django16: Django>=1.6,<1.7
3435
django17: Django>=1.7,<1.8
36+
django18: Django>=1.8,<1.9
3537
djangotrunk: https://github.com/django/django/tarball/master
3638
commands = coverage run -a --branch setup.py test

0 commit comments

Comments
 (0)