Skip to content

Commit

Permalink
Used remote_field instead of field.rel on Django 1.9+
Browse files Browse the repository at this point in the history
  • Loading branch information
charettes committed Dec 16, 2015
1 parent 7318c0c commit 8111fc0
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 34 deletions.
14 changes: 3 additions & 11 deletions mutant/compat.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import unicode_literals

from itertools import chain
from operator import attrgetter

import django
Expand All @@ -9,11 +8,8 @@


if django.VERSION >= (1, 8):
def get_fields(opts):
return opts.get_fields()

def get_rel_accessor_name(field):
return field.rel.get_accessor_name()
return get_remote_field(field).get_accessor_name()

def get_related_objects(opts):
return opts._get_fields(forward=False, reverse=True, include_hidden=True)
Expand All @@ -28,12 +24,6 @@ def clear_opts_related_cache(model_class):
for child in children:
clear_opts_related_cache(child)
else:
def get_fields(opts):
return chain(
opts.fields,
opts.many_to_many
)

def get_rel_accessor_name(field):
return field.related.get_accessor_name()

Expand Down Expand Up @@ -64,3 +54,5 @@ def clear_opts_related_cache(model_class):
pass
for child in children:
clear_opts_related_cache(child)

get_remote_field = attrgetter('remote_field' if django.VERSION >= (1, 9) else 'rel')
6 changes: 3 additions & 3 deletions mutant/contrib/related/management/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.db.models.fields.related import RelatedField
from django.utils.six import string_types

from ....compat import clear_opts_related_cache
from ....compat import clear_opts_related_cache, get_remote_field
from ....db.models import MutableModel
from ....models import ModelDefinition

Expand All @@ -20,13 +20,13 @@ def mutable_model_prepared(signal, sender, definition, existing_model_class,
if existing_model_class:
for field in existing_model_class._meta.local_fields:
if isinstance(field, RelatedField):
rel_to = field.rel.to
rel_to = get_remote_field(field).to
if not isinstance(rel_to, string_types):
referenced_models.add(rel_to)
# Add sender as a dependency of all mutable models it refers to
for field in sender._meta.local_fields:
if isinstance(field, RelatedField):
rel_to = field.rel.to
rel_to = get_remote_field(field).to
if not isinstance(rel_to, string_types):
referenced_models.add(rel_to)
if (issubclass(rel_to, MutableModel) and
Expand Down
3 changes: 2 additions & 1 deletion mutant/contrib/related/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.utils.translation import ugettext_lazy as _
from picklefield.fields import PickledObjectField

from ...compat import get_remote_field
from ...db.fields import PythonIdentifierField
from ...db.models import MutableModel
from ...models import FieldDefinition, FieldDefinitionManager, ModelDefinition
Expand Down Expand Up @@ -256,7 +257,7 @@ def clean(self):
through_class = self.through.model_class()
from_model = self.model_def.cached_model
for field in through_class._meta.fields:
rel_to = getattr(field.rel, 'to', None)
rel_to = getattr(get_remote_field(field), 'to', None)
if rel_to == from_model:
seen_from += 1
elif rel_to == to_model:
Expand Down
8 changes: 5 additions & 3 deletions mutant/db/fields/related.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.db.models.signals import class_prepared
from django.utils import six

from ...compat import get_remote_field
from ...models import ModelDefinition


Expand All @@ -27,10 +28,11 @@ def __validate(self, **kwargs):
"'%s'" % (opts.app_label, opts.object_name,
self.name, self.model_def_name))
else:
remote_field = get_remote_field(field)
if (not isinstance(field, fields.related.ForeignKey) or
(isinstance(field.rel.to, six.string_types) and
field.rel.to.lower() != 'mutant.modeldefinition') or
not issubclass(field.rel.to, ModelDefinition)):
(isinstance(remote_field.to, six.string_types) and
remote_field.to.lower() != 'mutant.modeldefinition') or
not issubclass(remote_field.to, ModelDefinition)):
raise ImproperlyConfigured("%s.%s.%s must refer to a ForeignKey "
"to `ModelDefinition`"
% (opts.app_label, opts.object_name,
Expand Down
7 changes: 5 additions & 2 deletions mutant/management/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.db.migrations.state import ModelState
from django.db.models.fields import FieldDoesNotExist

from ..compat import get_remote_field
from ..state import handler as state_handler
from ..utils import allow_migrate, popattr, remove_from_app_cache

Expand Down Expand Up @@ -51,10 +52,11 @@ def model_definition_post_save(sender, instance, created, **kwargs):
pass
else:
for column, field in extra_fields:
remote_field = get_remote_field(field)
if field.primary_key:
assert isinstance(primary_key, models.AutoField)
primary_key = field
elif (field.rel and field.rel.parent_link and
elif (remote_field and remote_field.parent_link and
isinstance(primary_key, models.AutoField)):
field.primary_key = True
primary_key = field
Expand Down Expand Up @@ -115,7 +117,8 @@ def base_definition_post_save(sender, instance, created, raw, **kwargs):
auto_pk = isinstance(opts.pk, models.AutoField)
for field in declared_fields:
field.model = model_class
if auto_pk and field.rel and field.rel.parent_link:
remote_field = get_remote_field(field)
if auto_pk and remote_field and remote_field.parent_link:
auto_pk = False
field.primary_key = True
perform_ddl('alter_field', model_class, opts.pk, field, strict=True)
Expand Down
8 changes: 4 additions & 4 deletions mutant/models/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
from picklefield.fields import PickledObjectField

from ... import logger
from ...compat import get_fields
from ...compat import get_remote_field
from ...db.deletion import CASCADE_MARK_ORIGIN
from ...db.fields import LazilyTranslatedField, PythonIdentifierField
from ...db.models import MutableModel
from ...signals import mutable_class_prepared
from ...state import handler as state_handler
from ...utils import get_db_table, remove_from_app_cache
from ...utils import get_db_table, get_foward_fields, remove_from_app_cache
from ..ordered import OrderedModel
from .managers import ModelDefinitionManager

Expand Down Expand Up @@ -388,7 +388,7 @@ def get_declared_fields(self):
if opts.abstract:
# Add fields inherited from base's abstract parent and
# local fields.
for field in get_fields(opts):
for field in get_foward_fields(opts):
if field.model is self.base or field.model._meta.abstract:
clone = field.clone()
clone.set_attributes_from_name(field.name)
Expand Down Expand Up @@ -433,7 +433,7 @@ def clean(self):
valid = False
else:
if isinstance(field, models.ForeignKey):
opts = field.rel.to._meta
opts = get_remote_field(field).to._meta
elif len(lookups): # Cannot go any deeper
valid = False
finally:
Expand Down
23 changes: 16 additions & 7 deletions mutant/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from collections import defaultdict
from contextlib import contextmanager
from copy import deepcopy
from itertools import groupby
from itertools import chain, groupby
from operator import itemgetter

from django.apps import AppConfig, apps
Expand All @@ -12,7 +12,9 @@
from django.utils.encoding import force_text
from django.utils.functional import lazy

from .compat import clear_opts_related_cache, get_fields, get_rel_accessor_name
from .compat import (
clear_opts_related_cache, get_rel_accessor_name, get_remote_field,
)


def allow_migrate(model):
Expand Down Expand Up @@ -85,14 +87,21 @@ def remove_from_app_cache(model_class, quiet=False):
return model_class


def get_foward_fields(opts):
return chain(
opts.fields,
opts.many_to_many
)


def unreference_model(model):
for field in get_fields(model._meta):
rel = getattr(field, 'rel', None)
if field.model is model and rel:
to = rel.to
for field in get_foward_fields(model._meta):
remote_field = get_remote_field(field)
if field.model is model and remote_field:
to = remote_field.to
if isinstance(to, models.base.ModelBase):
clear_opts_related_cache(to)
rel_is_hidden = rel.is_hidden()
rel_is_hidden = remote_field.is_hidden()
# An accessor is added to related classes if they are not
# hidden. However o2o fields *always* add an accessor
# even if the relationship is hidden.
Expand Down
8 changes: 5 additions & 3 deletions tests/test_contrib_related.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from django.db.models.fields import FieldDoesNotExist
from django.utils.translation import ugettext_lazy as _

from mutant.compat import get_related_model, get_related_objects
from mutant.compat import (
get_related_model, get_related_objects, get_remote_field,
)
from mutant.contrib.related.models import (
ForeignKeyDefinition, ManyToManyFieldDefinition,
)
Expand Down Expand Up @@ -129,7 +131,7 @@ def test_recursive_relationship(self):
)
self.assertTrue(fk.is_recursive_relationship)
Model = self.model_def.model_class()
self.assertEqual(Model._meta.get_field('f1').rel.to, Model)
self.assertEqual(get_remote_field(Model._meta.get_field('f1')).to, Model)
obj1 = Model.objects.create()
obj2 = Model.objects.create(f1=obj1)
obj1.f1 = obj2
Expand All @@ -156,7 +158,7 @@ def test_fixture_loading(self):
except FieldDoesNotExist:
self.fail('The fk field should be created')
to_model_class = to_model_def.model_class()
self.assertEqual(fk_field.rel.to, to_model_class)
self.assertEqual(get_remote_field(fk_field).to, to_model_class)
to_instance = to_model_class.objects.create()
from_instance = from_model_class.objects.create(fk=to_instance)
self.assertEqual(to_instance.froms.get(), from_instance)
Expand Down

0 comments on commit 8111fc0

Please sign in to comment.