Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
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
  • Loading branch information
Harper04 committed Jan 19, 2015
commit 067360c4ee721a22542e23310d42cf0a47b89991
2 changes: 1 addition & 1 deletion rest_framework/relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ def __init__(self, slug_field=None, **kwargs):

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})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure the only optimization is unrelated and should be removed.

except ObjectDoesNotExist:
self.fail('does_not_exist', slug_name=self.slug_field, value=smart_text(data))
except (TypeError, ValueError):
Expand Down
10 changes: 9 additions & 1 deletion rest_framework/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,7 @@ class ModelSerializer(Serializer):
models.URLField: URLField,
})
_related_class = PrimaryKeyRelatedField
_related_to_field_class = SlugRelatedField

def create(self, validated_data):
"""
Expand Down Expand Up @@ -1002,8 +1003,15 @@ def get_fields(self):
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you just do kwargs.pop('to_field', False) here instead of getting it, and then popping it on the next line?

if to_field:
# using the slug field for now
kwargs.pop('to_field', None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we are popping this just a few lines above, the line shouldn't be needed.

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)
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 @@ -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)
Expand All @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be kwargs['slug_field'] = to_field ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's being used in serializers.py with the check against id. If we determine that the check isn't actually needed, then I think we could get away with just using slug_field here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's being used in serializers.py with the check against id.

Sorry I didn't understand - you might need to link me to that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I named it to_field because mentally i am still treating it like a ForeignKey object at that point. Pointing it to a slug_field afterwards was just handy


if has_through_model:
kwargs['read_only'] = True
kwargs.pop('queryset', None)
Expand Down
6 changes: 6 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',
'to_many',
'to_field',
'has_through_model'
])

Expand Down Expand Up @@ -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
)

Expand All @@ -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
)
Expand Down