aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
authorTom Christie2014-01-13 17:38:03 +0000
committerTom Christie2014-01-13 17:38:03 +0000
commite91d0a69ab404a79da1dd5d0806d33e972a1a09b (patch)
tree16b002eeed52d39b7d803cb62c606edbddd821e9 /rest_framework
parentd937ce331cc6cd2df04a989b49cca030f65319da (diff)
parentc4d77667cf80588a2195fdc025bda53a5b977105 (diff)
downloaddjango-rest-framework-e91d0a69ab404a79da1dd5d0806d33e972a1a09b.tar.bz2
Merge branch 'testing-nested-serializers' of git://github.com/dustinfarris/django-rest-framework into dustinfarris-testing-nested-serializers
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/runtests/settings.py3
-rw-r--r--rest_framework/serializers.py28
-rw-r--r--rest_framework/tests/accounts/__init__.py0
-rw-r--r--rest_framework/tests/accounts/models.py8
-rw-r--r--rest_framework/tests/accounts/serializers.py11
-rw-r--r--rest_framework/tests/records/__init__.py0
-rw-r--r--rest_framework/tests/records/models.py6
-rw-r--r--rest_framework/tests/test_serializer_import.py19
-rw-r--r--rest_framework/tests/test_serializer_nested.py1
-rw-r--r--rest_framework/tests/test_serializers.py28
-rw-r--r--rest_framework/tests/users/__init__.py0
-rw-r--r--rest_framework/tests/users/models.py6
-rw-r--r--rest_framework/tests/users/serializers.py8
13 files changed, 116 insertions, 2 deletions
diff --git a/rest_framework/runtests/settings.py b/rest_framework/runtests/settings.py
index be721658..3fc0eb2f 100644
--- a/rest_framework/runtests/settings.py
+++ b/rest_framework/runtests/settings.py
@@ -100,6 +100,9 @@ INSTALLED_APPS = (
'rest_framework',
'rest_framework.authtoken',
'rest_framework.tests',
+ 'rest_framework.tests.accounts',
+ 'rest_framework.tests.records',
+ 'rest_framework.tests.users',
)
# OAuth is optional and won't work if there is no oauth_provider & oauth2
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index b22ca578..0ea2cadb 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -13,8 +13,10 @@ response content is handled by parsers and renderers.
from __future__ import unicode_literals
import copy
import datetime
+import inspect
import types
from decimal import Decimal
+from django.core.exceptions import ImproperlyConfigured
from django.core.paginator import Page
from django.db import models
from django.forms import widgets
@@ -32,6 +34,27 @@ from rest_framework.relations import *
from rest_framework.fields import *
+def _resolve_model(obj):
+ """
+ Resolve supplied `obj` to a Django model class.
+
+ `obj` must be a Django model class itself, or a string
+ representation of one. Useful in situtations like GH #1225 where
+ Django may not have resolved a string-based reference to a model in
+ another model's foreign key definition.
+
+ String representations should have the format:
+ 'appname.ModelName'
+ """
+ if type(obj) == str and len(obj.split('.')) == 2:
+ app_name, model_name = obj.split('.')
+ return models.get_model(app_name, model_name)
+ elif inspect.isclass(obj) and issubclass(obj, models.Model):
+ return obj
+ else:
+ raise ValueError("{0} is not a Django model".format(obj))
+
+
def pretty_name(name):
"""Converts 'first_name' to 'First name'"""
if not name:
@@ -656,7 +679,10 @@ class ModelSerializer(Serializer):
if model_field.rel:
to_many = isinstance(model_field,
models.fields.related.ManyToManyField)
- related_model = model_field.rel.to
+ try:
+ related_model = _resolve_model(model_field.rel.to)
+ except ValueError as error_message:
+ raise ImproperlyConfigured(error_message)
if to_many and not model_field.rel.through._meta.auto_created:
has_through_model = True
diff --git a/rest_framework/tests/accounts/__init__.py b/rest_framework/tests/accounts/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rest_framework/tests/accounts/__init__.py
diff --git a/rest_framework/tests/accounts/models.py b/rest_framework/tests/accounts/models.py
new file mode 100644
index 00000000..525e601b
--- /dev/null
+++ b/rest_framework/tests/accounts/models.py
@@ -0,0 +1,8 @@
+from django.db import models
+
+from rest_framework.tests.users.models import User
+
+
+class Account(models.Model):
+ owner = models.ForeignKey(User, related_name='accounts_owned')
+ admins = models.ManyToManyField(User, blank=True, null=True, related_name='accounts_administered')
diff --git a/rest_framework/tests/accounts/serializers.py b/rest_framework/tests/accounts/serializers.py
new file mode 100644
index 00000000..a27b9ca6
--- /dev/null
+++ b/rest_framework/tests/accounts/serializers.py
@@ -0,0 +1,11 @@
+from rest_framework import serializers
+
+from rest_framework.tests.accounts.models import Account
+from rest_framework.tests.users.serializers import UserSerializer
+
+
+class AccountSerializer(serializers.ModelSerializer):
+ admins = UserSerializer(many=True)
+
+ class Meta:
+ model = Account
diff --git a/rest_framework/tests/records/__init__.py b/rest_framework/tests/records/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rest_framework/tests/records/__init__.py
diff --git a/rest_framework/tests/records/models.py b/rest_framework/tests/records/models.py
new file mode 100644
index 00000000..76954807
--- /dev/null
+++ b/rest_framework/tests/records/models.py
@@ -0,0 +1,6 @@
+from django.db import models
+
+
+class Record(models.Model):
+ account = models.ForeignKey('accounts.Account', blank=True, null=True)
+ owner = models.ForeignKey('users.User', blank=True, null=True)
diff --git a/rest_framework/tests/test_serializer_import.py b/rest_framework/tests/test_serializer_import.py
new file mode 100644
index 00000000..9f30a7ff
--- /dev/null
+++ b/rest_framework/tests/test_serializer_import.py
@@ -0,0 +1,19 @@
+from django.test import TestCase
+
+from rest_framework import serializers
+from rest_framework.tests.accounts.serializers import AccountSerializer
+
+
+class ImportingModelSerializerTests(TestCase):
+ """
+ In some situations like, GH #1225, it is possible, especially in
+ testing, to import a serializer who's related models have not yet
+ been resolved by Django. `AccountSerializer` is an example of such
+ a serializer (imported at the top of this file).
+ """
+ def test_import_model_serializer(self):
+ """
+ The serializer at the top of this file should have been
+ imported successfully, and we should be able to instantiate it.
+ """
+ self.assertIsInstance(AccountSerializer(), serializers.ModelSerializer)
diff --git a/rest_framework/tests/test_serializer_nested.py b/rest_framework/tests/test_serializer_nested.py
index 7114a060..6d69ffbd 100644
--- a/rest_framework/tests/test_serializer_nested.py
+++ b/rest_framework/tests/test_serializer_nested.py
@@ -345,4 +345,3 @@ class NestedModelSerializerUpdateTests(TestCase):
result = deserialize.object
result.save()
self.assertEqual(result.id, john.id)
-
diff --git a/rest_framework/tests/test_serializers.py b/rest_framework/tests/test_serializers.py
new file mode 100644
index 00000000..082a400c
--- /dev/null
+++ b/rest_framework/tests/test_serializers.py
@@ -0,0 +1,28 @@
+from django.db import models
+from django.test import TestCase
+
+from rest_framework.serializers import _resolve_model
+from rest_framework.tests.models import BasicModel
+
+
+class ResolveModelTests(TestCase):
+ """
+ `_resolve_model` should return a Django model class given the
+ provided argument is a Django model class itself, or a properly
+ formatted string representation of one.
+ """
+ def test_resolve_django_model(self):
+ resolved_model = _resolve_model(BasicModel)
+ self.assertEqual(resolved_model, BasicModel)
+
+ def test_resolve_string_representation(self):
+ resolved_model = _resolve_model('tests.BasicModel')
+ self.assertEqual(resolved_model, BasicModel)
+
+ def test_resolve_non_django_model(self):
+ with self.assertRaises(ValueError):
+ _resolve_model(TestCase)
+
+ def test_resolve_improper_string_representation(self):
+ with self.assertRaises(ValueError):
+ _resolve_model('BasicModel')
diff --git a/rest_framework/tests/users/__init__.py b/rest_framework/tests/users/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rest_framework/tests/users/__init__.py
diff --git a/rest_framework/tests/users/models.py b/rest_framework/tests/users/models.py
new file mode 100644
index 00000000..128bac90
--- /dev/null
+++ b/rest_framework/tests/users/models.py
@@ -0,0 +1,6 @@
+from django.db import models
+
+
+class User(models.Model):
+ account = models.ForeignKey('accounts.Account', blank=True, null=True, related_name='users')
+ active_record = models.ForeignKey('records.Record', blank=True, null=True)
diff --git a/rest_framework/tests/users/serializers.py b/rest_framework/tests/users/serializers.py
new file mode 100644
index 00000000..da496554
--- /dev/null
+++ b/rest_framework/tests/users/serializers.py
@@ -0,0 +1,8 @@
+from rest_framework import serializers
+
+from rest_framework.tests.users.models import User
+
+
+class UserSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = User