Move models.resolve_model to serializers._resolve_model

This commit is contained in:
Dustin Farris 2014-01-13 11:47:44 -05:00
parent 2332382b51
commit b1b58762a3
3 changed files with 35 additions and 31 deletions

View File

@ -1,22 +1 @@
import inspect # Just to keep things like ./manage.py test happy
from django.db import models
def resolve_model(obj):
"""
Resolve supplied `obj` to a Django model class.
`obj` must be a Django model class, or a string representation
of one.
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 valid Django model".format(obj))

View File

@ -13,14 +13,15 @@ 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
from django.utils.datastructures import SortedDict from django.utils.datastructures import SortedDict
from rest_framework.compat import get_concrete_model, six from rest_framework.compat import get_concrete_model, six
from rest_framework.models import resolve_model
# Note: We do the following so that users of the framework can use this style: # Note: We do the following so that users of the framework can use this style:
# #
@ -33,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:
@ -657,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 = resolve_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

@ -1,28 +1,28 @@
from django.db import models from django.db import models
from django.test import TestCase from django.test import TestCase
from rest_framework.models import resolve_model from rest_framework.serializers import _resolve_model
from rest_framework.tests.models import BasicModel from rest_framework.tests.models import BasicModel
class ResolveModelTests(TestCase): class ResolveModelTests(TestCase):
""" """
`resolve_model` should return a Django model class given the `_resolve_model` should return a Django model class given the
provided argument is a Django model class itself, or a properly provided argument is a Django model class itself, or a properly
formatted string representation of one. formatted string representation of one.
""" """
def test_resolve_django_model(self): def test_resolve_django_model(self):
resolved_model = resolve_model(BasicModel) resolved_model = _resolve_model(BasicModel)
self.assertEqual(resolved_model, BasicModel) self.assertEqual(resolved_model, BasicModel)
def test_resolve_string_representation(self): def test_resolve_string_representation(self):
resolved_model = resolve_model('tests.BasicModel') resolved_model = _resolve_model('tests.BasicModel')
self.assertEqual(resolved_model, BasicModel) self.assertEqual(resolved_model, BasicModel)
def test_resolve_non_django_model(self): def test_resolve_non_django_model(self):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
resolve_model(TestCase) _resolve_model(TestCase)
def test_resolve_with_improper_string_representation(self): def test_resolve_improper_string_representation(self):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
resolve_model('BasicModel') _resolve_model('BasicModel')