diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 7a0aea3db..af3a4b007 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -58,6 +58,7 @@ def distinct(queryset, base): return queryset.distinct() +# Obtaining manager instances and names from model options differs after 1.10. def get_names_and_managers(options): if django.VERSION >= (1, 10): # Django 1.10 onwards provides a `.managers` property on the Options. @@ -75,6 +76,18 @@ def get_names_and_managers(options): ] +# field.rel is deprecated from 1.9 onwards +def get_remote_field(field, **kwargs): + if 'default' in kwargs: + if django.VERSION < (1, 9): + return getattr(field, 'rel', kwargs['default']) + return getattr(field, 'remote_field', kwargs['default']) + + if django.VERSION < (1, 9): + return field.rel + return field.remote_field + + # contrib.postgres only supported from 1.8 onwards. try: from django.contrib.postgres import fields as postgres_fields diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 5eb1b3b4c..4f34164c2 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -30,7 +30,7 @@ from django.utils.ipv6 import clean_ipv6_address from django.utils.translation import ugettext_lazy as _ from rest_framework import ISO_8601 -from rest_framework.compat import unicode_repr, unicode_to_repr +from rest_framework.compat import get_remote_field, unicode_repr, unicode_to_repr from rest_framework.exceptions import ValidationError from rest_framework.settings import api_settings from rest_framework.utils import html, humanize_datetime, representation @@ -1674,7 +1674,7 @@ class ModelField(Field): self.validators.append(MaxLengthValidator(max_length, message=message)) def to_internal_value(self, data): - rel = getattr(self.model_field, 'rel', None) + rel = get_remote_field(self.model_field, default=None) if rel is not None: return rel.to._meta.get_field(rel.field_name).to_python(data) return self.model_field.to_python(data) diff --git a/rest_framework/utils/model_meta.py b/rest_framework/utils/model_meta.py index c3424a679..e097f5ef6 100644 --- a/rest_framework/utils/model_meta.py +++ b/rest_framework/utils/model_meta.py @@ -13,6 +13,9 @@ from django.core.exceptions import ImproperlyConfigured from django.db import models from django.utils import six +from rest_framework.compat import get_remote_field + + FieldInfo = namedtuple('FieldResult', [ 'pk', # Model field instance 'fields', # Dict of field name -> model field instance @@ -76,16 +79,19 @@ def get_field_info(model): def _get_pk(opts): pk = opts.pk - while pk.rel and pk.rel.parent_link: + rel = get_remote_field(pk) + + while rel and rel.parent_link: # If model is a child via multi-table inheritance, use parent's pk. - pk = pk.rel.to._meta.pk + pk = rel.to._meta.pk + rel = get_remote_field(pk) return pk def _get_fields(opts): fields = OrderedDict() - for field in [field for field in opts.fields if field.serialize and not field.rel]: + for field in [field for field in opts.fields if field.serialize and not get_remote_field(field)]: fields[field.name] = field return fields @@ -100,10 +106,10 @@ def _get_forward_relationships(opts): Returns an `OrderedDict` of field names to `RelationInfo`. """ forward_relations = OrderedDict() - for field in [field for field in opts.fields if field.serialize and field.rel]: + for field in [field for field in opts.fields if field.serialize and get_remote_field(field)]: forward_relations[field.name] = RelationInfo( model_field=field, - related_model=_resolve_model(field.rel.to), + related_model=_resolve_model(get_remote_field(field).to), to_many=False, to_field=_get_to_field(field), has_through_model=False @@ -113,12 +119,12 @@ def _get_forward_relationships(opts): for field in [field for field in opts.many_to_many if field.serialize]: forward_relations[field.name] = RelationInfo( model_field=field, - related_model=_resolve_model(field.rel.to), + related_model=_resolve_model(get_remote_field(field).to), to_many=True, # manytomany do not have to_fields to_field=None, has_through_model=( - not field.rel.through._meta.auto_created + not get_remote_field(field).through._meta.auto_created ) ) @@ -141,7 +147,7 @@ def _get_reverse_relationships(opts): reverse_relations[accessor_name] = RelationInfo( model_field=None, related_model=related, - to_many=relation.field.rel.multiple, + to_many=get_remote_field(relation.field).multiple, to_field=_get_to_field(relation.field), has_through_model=False ) @@ -158,8 +164,8 @@ def _get_reverse_relationships(opts): # manytomany do not have to_fields to_field=None, has_through_model=( - (getattr(relation.field.rel, 'through', None) is not None) and - not relation.field.rel.through._meta.auto_created + (getattr(get_remote_field(relation.field), 'through', None) is not None) and + not get_remote_field(relation.field).through._meta.auto_created ) )