Merge branch 'testing-nested-serializers' of git://github.com/dustinfarris/django-rest-framework into dustinfarris-testing-nested-serializers

This commit is contained in:
Tom Christie 2014-01-13 17:38:03 +00:00
commit e91d0a69ab
13 changed files with 116 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -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

View File

View File

@ -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)

View File

@ -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)

View File

@ -345,4 +345,3 @@ class NestedModelSerializerUpdateTests(TestCase):
result = deserialize.object
result.save()
self.assertEqual(result.id, john.id)

View File

@ -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')

View File

View File

@ -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)

View File

@ -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