diff options
| author | Tom Christie | 2014-01-13 17:38:03 +0000 | 
|---|---|---|
| committer | Tom Christie | 2014-01-13 17:38:03 +0000 | 
| commit | e91d0a69ab404a79da1dd5d0806d33e972a1a09b (patch) | |
| tree | 16b002eeed52d39b7d803cb62c606edbddd821e9 /rest_framework | |
| parent | d937ce331cc6cd2df04a989b49cca030f65319da (diff) | |
| parent | c4d77667cf80588a2195fdc025bda53a5b977105 (diff) | |
| download | django-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.py | 3 | ||||
| -rw-r--r-- | rest_framework/serializers.py | 28 | ||||
| -rw-r--r-- | rest_framework/tests/accounts/__init__.py | 0 | ||||
| -rw-r--r-- | rest_framework/tests/accounts/models.py | 8 | ||||
| -rw-r--r-- | rest_framework/tests/accounts/serializers.py | 11 | ||||
| -rw-r--r-- | rest_framework/tests/records/__init__.py | 0 | ||||
| -rw-r--r-- | rest_framework/tests/records/models.py | 6 | ||||
| -rw-r--r-- | rest_framework/tests/test_serializer_import.py | 19 | ||||
| -rw-r--r-- | rest_framework/tests/test_serializer_nested.py | 1 | ||||
| -rw-r--r-- | rest_framework/tests/test_serializers.py | 28 | ||||
| -rw-r--r-- | rest_framework/tests/users/__init__.py | 0 | ||||
| -rw-r--r-- | rest_framework/tests/users/models.py | 6 | ||||
| -rw-r--r-- | rest_framework/tests/users/serializers.py | 8 | 
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  | 
