This commit is contained in:
Harper04 2015-06-25 15:41:49 +00:00
commit 1ebfbfee0f
4 changed files with 33 additions and 1 deletions

View File

@ -170,6 +170,21 @@ else:
super(MaxLengthValidator, self).__init__(*args, **kwargs) 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.rel.field_name
# URLValidator only accepts `message` in 1.6+ # URLValidator only accepts `message` in 1.6+
if django.VERSION >= (1, 6): if django.VERSION >= (1, 6):
from django.core.validators import URLValidator from django.core.validators import URLValidator

View File

@ -751,6 +751,7 @@ class ModelSerializer(Serializer):
if ModelDurationField is not None: if ModelDurationField is not None:
serializer_field_mapping[ModelDurationField] = DurationField serializer_field_mapping[ModelDurationField] = DurationField
serializer_related_field = PrimaryKeyRelatedField serializer_related_field = PrimaryKeyRelatedField
serializer_related_to_field = SlugRelatedField
serializer_url_field = HyperlinkedIdentityField serializer_url_field = HyperlinkedIdentityField
serializer_choice_field = ChoiceField serializer_choice_field = ChoiceField
@ -1044,6 +1045,11 @@ class ModelSerializer(Serializer):
field_class = self.serializer_related_field field_class = self.serializer_related_field
field_kwargs = get_relation_kwargs(field_name, relation_info) field_kwargs = get_relation_kwargs(field_name, relation_info)
to_field = field_kwargs.pop('to_field', None)
if to_field and to_field != 'id':
field_kwargs['slug_field'] = to_field
field_class = self.serializer_related_to_field
# `view_name` is only valid for hyperlinked relationships. # `view_name` is only valid for hyperlinked relationships.
if not issubclass(field_class, HyperlinkedRelatedField): if not issubclass(field_class, HyperlinkedRelatedField):
field_kwargs.pop('view_name', None) field_kwargs.pop('view_name', None)

View File

@ -198,7 +198,7 @@ def get_relation_kwargs(field_name, relation_info):
""" """
Creates a default instance of a flat relational field. Creates a default instance of a flat relational field.
""" """
model_field, related_model, to_many, has_through_model = relation_info model_field, related_model, to_many, to_field, has_through_model = relation_info
kwargs = { kwargs = {
'queryset': related_model._default_manager, 'queryset': related_model._default_manager,
'view_name': get_detail_view_name(related_model) 'view_name': get_detail_view_name(related_model)
@ -207,6 +207,9 @@ def get_relation_kwargs(field_name, relation_info):
if to_many: if to_many:
kwargs['many'] = True kwargs['many'] = True
if to_field:
kwargs['to_field'] = to_field
if has_through_model: if has_through_model:
kwargs['read_only'] = True kwargs['read_only'] = True
kwargs.pop('queryset', None) kwargs.pop('queryset', None)

View File

@ -9,6 +9,7 @@ from collections import namedtuple
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.db import models from django.db import models
from django.utils import six from django.utils import six
from rest_framework.compat import get_to_field
from rest_framework.compat import OrderedDict from rest_framework.compat import OrderedDict
import inspect import inspect
@ -26,6 +27,7 @@ RelationInfo = namedtuple('RelationInfo', [
'model_field', 'model_field',
'related_model', 'related_model',
'to_many', 'to_many',
'to_field',
'has_through_model' 'has_through_model'
]) ])
@ -100,6 +102,7 @@ def _get_forward_relationships(opts):
model_field=field, model_field=field,
related_model=_resolve_model(field.rel.to), related_model=_resolve_model(field.rel.to),
to_many=False, to_many=False,
to_field=get_to_field(field),
has_through_model=False has_through_model=False
) )
@ -109,6 +112,8 @@ def _get_forward_relationships(opts):
model_field=field, model_field=field,
related_model=_resolve_model(field.rel.to), related_model=_resolve_model(field.rel.to),
to_many=True, to_many=True,
# manytomany do not have to_fields
to_field=None,
has_through_model=( has_through_model=(
not field.rel.through._meta.auto_created not field.rel.through._meta.auto_created
) )
@ -133,6 +138,7 @@ def _get_reverse_relationships(opts):
model_field=None, model_field=None,
related_model=related, related_model=related,
to_many=relation.field.rel.multiple, to_many=relation.field.rel.multiple,
to_field=get_to_field(relation.field),
has_through_model=False has_through_model=False
) )
@ -144,6 +150,8 @@ def _get_reverse_relationships(opts):
model_field=None, model_field=None,
related_model=related, related_model=related,
to_many=True, to_many=True,
# manytomany do not have to_fields
to_field=None,
has_through_model=( has_through_model=(
(getattr(relation.field.rel, 'through', None) is not None) and (getattr(relation.field.rel, 'through', None) is not None) and
not relation.field.rel.through._meta.auto_created not relation.field.rel.through._meta.auto_created