From f808b6c6bc8c78df5bed5ddeb1556c21fc09bd5b Mon Sep 17 00:00:00 2001 From: Tom Jaster Date: Tue, 20 Jan 2015 21:40:23 +0100 Subject: [PATCH] * Removed SlugRelatedField optimization * Moved compatibility check of to_fields to compat.py * Expanded the check with a way that should work on django <1.6. Need to check trevis after pushing.. --- rest_framework/compat.py | 15 +++++++++++++++ rest_framework/relations.py | 9 +-------- rest_framework/utils/model_meta.py | 18 +++--------------- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 971dee9cf..cf820af42 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -138,6 +138,21 @@ else: super(MaxLengthValidator, self).__init__(*args, **kwargs) +# ForeignKey's to_fields parameter was changed in Django 1.6 to an array named to_fields +# to_fields is an array but django lets you only set one to_field for ForeignKeys +# https://docs.djangoproject.com/en/1.7/ref/models/fields/#django.db.models.ForeignKey.to_field +# see also ForeignKey and ForeignObject in +# https://docs.djangoproject.com/en/1.7/_modules/django/db/models/fields/related/ + +if django.VERSION >= (1, 6): + def get_to_field(field): + # This should work for casual ForeignKeys + return field.to_fields[0] if len(field.to_fields) else None +else: + def get_to_field(field): + return field.to_field + + # URLValidator only accepts `message` in 1.6+ if django.VERSION >= (1, 6): from django.core.validators import URLValidator diff --git a/rest_framework/relations.py b/rest_framework/relations.py index b1a7eca65..3a081fa65 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -303,14 +303,7 @@ class SlugRelatedField(RelatedField): def to_internal_value(self, data): try: - # Some tests do not have the full QuerySet API - # But we optimize SlugRelatedFields by only loading what we need - qs = self.get_queryset() - if hasattr(qs, 'only'): - return self.get_queryset().only(self.slug_field).get(**{self.slug_field: data}) - else: - return self.get_queryset().get(**{self.slug_field: data}) - + return self.get_queryset().only(self.slug_field).get(**{self.slug_field: data}) except ObjectDoesNotExist: self.fail('does_not_exist', slug_name=self.slug_field, value=smart_text(data)) except (TypeError, ValueError): diff --git a/rest_framework/utils/model_meta.py b/rest_framework/utils/model_meta.py index caa93d4af..e088fe2a9 100644 --- a/rest_framework/utils/model_meta.py +++ b/rest_framework/utils/model_meta.py @@ -9,6 +9,7 @@ from collections import namedtuple from django.core.exceptions import ImproperlyConfigured from django.db import models from django.utils import six +from rest_framework.compat import get_to_field from rest_framework.compat import OrderedDict import inspect @@ -97,18 +98,11 @@ def _get_forward_relationships(opts): """ forward_relations = OrderedDict() for field in [field for field in opts.fields if field.serialize and field.rel]: - # For < django 1.6 - if hasattr(field, 'to_fields'): - to_field = field.to_fields[0] if len(field.to_fields) else None - else: - to_field = None - forward_relations[field.name] = RelationInfo( model_field=field, related=_resolve_model(field.rel.to), to_many=False, - # to_fields is an array but django lets you only set one to_field - to_field=to_field, + to_field=get_to_field(field), has_through_model=False ) @@ -135,17 +129,11 @@ def _get_reverse_relationships(opts): reverse_relations = OrderedDict() for relation in opts.get_all_related_objects(): accessor_name = relation.get_accessor_name() - # For < django 1.6 - if hasattr(relation.field, 'to_fields'): - to_field = relation.field.to_fields[0] if len(relation.field.to_fields) else None - else: - to_field = None - reverse_relations[accessor_name] = RelationInfo( model_field=None, related=relation.model, to_many=relation.field.rel.multiple, - to_field=to_field, + to_field=get_to_field(relation.field), has_through_model=False )