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',
'rest_framework.authtoken', 'rest_framework.authtoken',
'rest_framework.tests', '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 # 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 from __future__ import unicode_literals
import copy import copy
import datetime import datetime
import inspect
import types import types
from decimal import Decimal from decimal import Decimal
from django.core.exceptions import ImproperlyConfigured
from django.core.paginator import Page from django.core.paginator import Page
from django.db import models from django.db import models
from django.forms import widgets from django.forms import widgets
@ -32,6 +34,27 @@ from rest_framework.relations import *
from rest_framework.fields 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): def pretty_name(name):
"""Converts 'first_name' to 'First name'""" """Converts 'first_name' to 'First name'"""
if not name: if not name:
@ -656,7 +679,10 @@ class ModelSerializer(Serializer):
if model_field.rel: if model_field.rel:
to_many = isinstance(model_field, to_many = isinstance(model_field,
models.fields.related.ManyToManyField) 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: if to_many and not model_field.rel.through._meta.auto_created:
has_through_model = True 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 = deserialize.object
result.save() result.save()
self.assertEqual(result.id, john.id) 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