Skip to content

Commit 322bda8

Browse files
committed
Added support for the to_field on ForeignKey fields
1 parent c68d932 commit 322bda8

File tree

3 files changed

+21
-1
lines changed

3 files changed

+21
-1
lines changed

rest_framework/serializers.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ class ModelSerializer(Serializer):
794794
if ModelJSONField is not None:
795795
serializer_field_mapping[ModelJSONField] = JSONField
796796
serializer_related_field = PrimaryKeyRelatedField
797+
serializer_related_to_field = SlugRelatedField
797798
serializer_url_field = HyperlinkedIdentityField
798799
serializer_choice_field = ChoiceField
799800

@@ -1129,6 +1130,11 @@ def build_relational_field(self, field_name, relation_info):
11291130
field_class = self.serializer_related_field
11301131
field_kwargs = get_relation_kwargs(field_name, relation_info)
11311132

1133+
to_field = field_kwargs.pop('to_field', None)
1134+
if to_field and to_field != 'id':
1135+
field_kwargs['slug_field'] = to_field
1136+
field_class = self.serializer_related_to_field
1137+
11321138
# `view_name` is only valid for hyperlinked relationships.
11331139
if not issubclass(field_class, HyperlinkedRelatedField):
11341140
field_kwargs.pop('view_name', None)

rest_framework/utils/field_mapping.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ def get_relation_kwargs(field_name, relation_info):
222222
"""
223223
Creates a default instance of a flat relational field.
224224
"""
225-
model_field, related_model, to_many, has_through_model = relation_info
225+
model_field, related_model, to_many, to_field, has_through_model = relation_info
226226
kwargs = {
227227
'queryset': related_model._default_manager,
228228
'view_name': get_detail_view_name(related_model)
@@ -231,6 +231,9 @@ def get_relation_kwargs(field_name, relation_info):
231231
if to_many:
232232
kwargs['many'] = True
233233

234+
if to_field:
235+
kwargs['to_field'] = to_field
236+
234237
if has_through_model:
235238
kwargs['read_only'] = True
236239
kwargs.pop('queryset', None)

rest_framework/utils/model_meta.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
'model_field',
2727
'related_model',
2828
'to_many',
29+
'to_field',
2930
'has_through_model'
3031
])
3132

@@ -90,6 +91,10 @@ def _get_fields(opts):
9091
return fields
9192

9293

94+
def _get_to_field(field):
95+
return field.to_fields[0] if field.to_fields else None
96+
97+
9398
def _get_forward_relationships(opts):
9499
"""
95100
Returns an `OrderedDict` of field names to `RelationInfo`.
@@ -100,6 +105,7 @@ def _get_forward_relationships(opts):
100105
model_field=field,
101106
related_model=_resolve_model(field.rel.to),
102107
to_many=False,
108+
to_field=_get_to_field(field),
103109
has_through_model=False
104110
)
105111

@@ -109,6 +115,8 @@ def _get_forward_relationships(opts):
109115
model_field=field,
110116
related_model=_resolve_model(field.rel.to),
111117
to_many=True,
118+
# manytomany do not have to_fields
119+
to_field=None,
112120
has_through_model=(
113121
not field.rel.through._meta.auto_created
114122
)
@@ -133,6 +141,7 @@ def _get_reverse_relationships(opts):
133141
model_field=None,
134142
related_model=related,
135143
to_many=relation.field.rel.multiple,
144+
to_field=_get_to_field(relation.field),
136145
has_through_model=False
137146
)
138147

@@ -144,6 +153,8 @@ def _get_reverse_relationships(opts):
144153
model_field=None,
145154
related_model=related,
146155
to_many=True,
156+
# manytomany do not have to_fields
157+
to_field=None,
147158
has_through_model=(
148159
(getattr(relation.field.rel, 'through', None) is not None) and
149160
not relation.field.rel.through._meta.auto_created

0 commit comments

Comments
 (0)