From 067360c4ee721a22542e23310d42cf0a47b89991 Mon Sep 17 00:00:00 2001 From: Tom Jaster Date: Mon, 19 Jan 2015 14:55:35 +0100 Subject: [PATCH] Added support for the to_field on ForeignKey Fields. Uses the SlugRelatedField instead. SlugRelatedField will only get the Slugfield from the ORM as it does not need the other stuff --- rest_framework/relations.py | 2 +- rest_framework/serializers.py | 10 +++++++++- rest_framework/utils/field_mapping.py | 5 ++++- rest_framework/utils/model_meta.py | 6 ++++++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/rest_framework/relations.py b/rest_framework/relations.py index aa0c2defe..3a081fa65 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -303,7 +303,7 @@ class SlugRelatedField(RelatedField): def to_internal_value(self, data): try: - 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/serializers.py b/rest_framework/serializers.py index e373cd107..c7c751f11 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -727,6 +727,7 @@ class ModelSerializer(Serializer): models.URLField: URLField, }) _related_class = PrimaryKeyRelatedField + _related_to_field_class = SlugRelatedField def create(self, validated_data): """ @@ -1002,8 +1003,15 @@ class ModelSerializer(Serializer): field_cls = self._get_nested_class(depth, relation_info) kwargs = get_nested_relation_kwargs(relation_info) else: - field_cls = self._related_class kwargs = get_relation_kwargs(field_name, relation_info) + to_field = kwargs.get('to_field', False) + if to_field: + # using the slug field for now + kwargs.pop('to_field', None) + kwargs['slug_field'] = to_field + field_cls = self._related_to_field_class + else: + field_cls = self._related_class # `view_name` is only valid for hyperlinked relationships. if not issubclass(field_cls, HyperlinkedRelatedField): kwargs.pop('view_name', None) diff --git a/rest_framework/utils/field_mapping.py b/rest_framework/utils/field_mapping.py index cba40d318..b48f58c02 100644 --- a/rest_framework/utils/field_mapping.py +++ b/rest_framework/utils/field_mapping.py @@ -194,7 +194,7 @@ def get_relation_kwargs(field_name, relation_info): """ 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 = { 'queryset': related_model._default_manager, 'view_name': get_detail_view_name(related_model) @@ -203,6 +203,9 @@ def get_relation_kwargs(field_name, relation_info): if to_many: kwargs['many'] = True + if to_field: + kwargs['to_field'] = to_field + if has_through_model: kwargs['read_only'] = True kwargs.pop('queryset', None) diff --git a/rest_framework/utils/model_meta.py b/rest_framework/utils/model_meta.py index 375d2e8c6..0f57d14f0 100644 --- a/rest_framework/utils/model_meta.py +++ b/rest_framework/utils/model_meta.py @@ -26,6 +26,7 @@ RelationInfo = namedtuple('RelationInfo', [ 'model_field', 'related', 'to_many', + 'to_field', 'has_through_model' ]) @@ -96,10 +97,13 @@ def _get_forward_relationships(opts): """ forward_relations = OrderedDict() for field in [field for field in opts.fields if field.serialize and field.rel]: + 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=field.to_fields[0] if len(field.to_fields) else None, has_through_model=False ) @@ -109,6 +113,8 @@ def _get_forward_relationships(opts): model_field=field, related=_resolve_model(field.rel.to), to_many=True, + # to_fields is an array but django lets you only set one to_field + to_field=field.to_fields[0] if len(field.to_fields) else None, has_through_model=( not field.rel.through._meta.auto_created )