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
This commit is contained in:
Tom Jaster 2015-01-19 14:55:35 +01:00
parent 4f27b966a5
commit 067360c4ee
4 changed files with 20 additions and 3 deletions

View File

@ -303,7 +303,7 @@ class SlugRelatedField(RelatedField):
def to_internal_value(self, data): def to_internal_value(self, data):
try: 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: except ObjectDoesNotExist:
self.fail('does_not_exist', slug_name=self.slug_field, value=smart_text(data)) self.fail('does_not_exist', slug_name=self.slug_field, value=smart_text(data))
except (TypeError, ValueError): except (TypeError, ValueError):

View File

@ -727,6 +727,7 @@ class ModelSerializer(Serializer):
models.URLField: URLField, models.URLField: URLField,
}) })
_related_class = PrimaryKeyRelatedField _related_class = PrimaryKeyRelatedField
_related_to_field_class = SlugRelatedField
def create(self, validated_data): def create(self, validated_data):
""" """
@ -1002,8 +1003,15 @@ class ModelSerializer(Serializer):
field_cls = self._get_nested_class(depth, relation_info) field_cls = self._get_nested_class(depth, relation_info)
kwargs = get_nested_relation_kwargs(relation_info) kwargs = get_nested_relation_kwargs(relation_info)
else: else:
field_cls = self._related_class
kwargs = get_relation_kwargs(field_name, relation_info) 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. # `view_name` is only valid for hyperlinked relationships.
if not issubclass(field_cls, HyperlinkedRelatedField): if not issubclass(field_cls, HyperlinkedRelatedField):
kwargs.pop('view_name', None) kwargs.pop('view_name', None)

View File

@ -194,7 +194,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)
@ -203,6 +203,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

@ -26,6 +26,7 @@ RelationInfo = namedtuple('RelationInfo', [
'model_field', 'model_field',
'related', 'related',
'to_many', 'to_many',
'to_field',
'has_through_model' 'has_through_model'
]) ])
@ -96,10 +97,13 @@ def _get_forward_relationships(opts):
""" """
forward_relations = OrderedDict() forward_relations = OrderedDict()
for field in [field for field in opts.fields if field.serialize and field.rel]: for field in [field for field in opts.fields if field.serialize and field.rel]:
forward_relations[field.name] = RelationInfo( forward_relations[field.name] = RelationInfo(
model_field=field, model_field=field,
related=_resolve_model(field.rel.to), related=_resolve_model(field.rel.to),
to_many=False, 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 has_through_model=False
) )
@ -109,6 +113,8 @@ def _get_forward_relationships(opts):
model_field=field, model_field=field,
related=_resolve_model(field.rel.to), related=_resolve_model(field.rel.to),
to_many=True, 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=( has_through_model=(
not field.rel.through._meta.auto_created not field.rel.through._meta.auto_created
) )