Skip to content

Commit

Permalink
Added support for the to_field on ForeignKey fields
Browse files Browse the repository at this point in the history
  • Loading branch information
likeon committed Oct 21, 2015
1 parent c68d932 commit 322bda8
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 1 deletion.
6 changes: 6 additions & 0 deletions rest_framework/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,7 @@ class ModelSerializer(Serializer):
if ModelJSONField is not None:
serializer_field_mapping[ModelJSONField] = JSONField
serializer_related_field = PrimaryKeyRelatedField
serializer_related_to_field = SlugRelatedField
serializer_url_field = HyperlinkedIdentityField
serializer_choice_field = ChoiceField

Expand Down Expand Up @@ -1129,6 +1130,11 @@ def build_relational_field(self, field_name, relation_info):
field_class = self.serializer_related_field
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.
if not issubclass(field_class, HyperlinkedRelatedField):
field_kwargs.pop('view_name', None)
Expand Down
5 changes: 4 additions & 1 deletion rest_framework/utils/field_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,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)
Expand All @@ -231,6 +231,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)
Expand Down
11 changes: 11 additions & 0 deletions rest_framework/utils/model_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
'model_field',
'related_model',
'to_many',
'to_field',
'has_through_model'
])

Expand Down Expand Up @@ -90,6 +91,10 @@ def _get_fields(opts):
return fields


def _get_to_field(field):
return field.to_fields[0] if field.to_fields else None


def _get_forward_relationships(opts):
"""
Returns an `OrderedDict` of field names to `RelationInfo`.
Expand All @@ -100,6 +105,7 @@ def _get_forward_relationships(opts):
model_field=field,
related_model=_resolve_model(field.rel.to),
to_many=False,
to_field=_get_to_field(field),
has_through_model=False
)

Expand All @@ -109,6 +115,8 @@ def _get_forward_relationships(opts):
model_field=field,
related_model=_resolve_model(field.rel.to),
to_many=True,
# manytomany do not have to_fields
to_field=None,
has_through_model=(
not field.rel.through._meta.auto_created
)
Expand All @@ -133,6 +141,7 @@ def _get_reverse_relationships(opts):
model_field=None,
related_model=related,
to_many=relation.field.rel.multiple,
to_field=_get_to_field(relation.field),
has_through_model=False
)

Expand All @@ -144,6 +153,8 @@ def _get_reverse_relationships(opts):
model_field=None,
related_model=related,
to_many=True,
# 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
Expand Down

0 comments on commit 322bda8

Please sign in to comment.