From 693892ed0104b8ce8cd801e7bec6107feeb88782 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 4 Oct 2012 22:07:24 +0100 Subject: [PATCH] Fix for field to make it easier to access field relationships --- rest_framework/fields.py | 6 ++++- rest_framework/tests/genericrelations.py | 33 ++++++++++++++++++++++++ rest_framework/tests/models.py | 24 +++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 rest_framework/tests/genericrelations.py diff --git a/rest_framework/fields.py b/rest_framework/fields.py index be9182357..b9ac37768 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -83,6 +83,10 @@ class Field(object): if is_protected_type(value): return value + + all_callable = getattr(value, 'all', None) + if is_simple_callable(all_callable): + return [self.to_native(item) for item in value.all()] elif hasattr(value, '__iter__') and not isinstance(value, (dict, basestring)): return [self.to_native(item) for item in value] return smart_unicode(value) @@ -197,7 +201,7 @@ class ModelField(WritableField): value = self.model_field._get_val_from_obj(obj) if is_protected_type(value): return value - return self.model_field.value_to_string(self.obj) + return self.model_field.value_to_string(obj) def attributes(self): return { diff --git a/rest_framework/tests/genericrelations.py b/rest_framework/tests/genericrelations.py new file mode 100644 index 000000000..d88a6c06e --- /dev/null +++ b/rest_framework/tests/genericrelations.py @@ -0,0 +1,33 @@ +from django.test import TestCase +from rest_framework import serializers +from rest_framework.tests.models import * + + +class TestGenericRelations(TestCase): + def setUp(self): + bookmark = Bookmark(url='https://www.djangoproject.com/') + bookmark.save() + django = Tag(tag_name='django') + django.save() + python = Tag(tag_name='python') + python.save() + t1 = TaggedItem(content_object=bookmark, tag=django) + t1.save() + t2 = TaggedItem(content_object=bookmark, tag=python) + t2.save() + self.bookmark = bookmark + + def test_reverse_generic_relation(self): + class BookmarkSerializer(serializers.ModelSerializer): + tags = serializers.Field(source='tags') + + class Meta: + model = Bookmark + exclude = ('id',) + + serializer = BookmarkSerializer(instance=self.bookmark) + expected = { + 'tags': [u'django', u'python'], + 'url': u'https://www.djangoproject.com/' + } + self.assertEquals(serializer.data, expected) diff --git a/rest_framework/tests/models.py b/rest_framework/tests/models.py index 969c82978..7c7f485b1 100644 --- a/rest_framework/tests/models.py +++ b/rest_framework/tests/models.py @@ -1,4 +1,7 @@ from django.db import models +from django.contrib.contenttypes.models import ContentType +from django.contrib.contenttypes.generic import GenericForeignKey, GenericRelation + # from django.contrib.auth.models import Group @@ -59,3 +62,24 @@ class CallableDefaultValueModel(RESTFrameworkModel): class ManyToManyModel(RESTFrameworkModel): rel = models.ManyToManyField(Anchor) + +# Models to test generic relations + + +class Tag(RESTFrameworkModel): + tag_name = models.SlugField() + + +class TaggedItem(RESTFrameworkModel): + tag = models.ForeignKey(Tag, related_name='items') + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + content_object = GenericForeignKey('content_type', 'object_id') + + def __unicode__(self): + return self.tag.tag_name + + +class Bookmark(RESTFrameworkModel): + url = models.URLField() + tags = GenericRelation(TaggedItem)