Commit e91d0a69 by Tom Christie

Merge branch 'testing-nested-serializers' of…

Merge branch 'testing-nested-serializers' of git://github.com/dustinfarris/django-rest-framework into dustinfarris-testing-nested-serializers
parents d937ce33 c4d77667
...@@ -100,6 +100,9 @@ INSTALLED_APPS = ( ...@@ -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
......
...@@ -13,8 +13,10 @@ response content is handled by parsers and renderers. ...@@ -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 * ...@@ -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): ...@@ -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
......
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')
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
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)
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)
...@@ -345,4 +345,3 @@ class NestedModelSerializerUpdateTests(TestCase): ...@@ -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)
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')
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)
from rest_framework import serializers
from rest_framework.tests.users.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment