aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/topics/3.0-announcement.md6
-rw-r--r--rest_framework/relations.py32
-rw-r--r--rest_framework/renderers.py5
-rw-r--r--rest_framework/serializers.py60
-rw-r--r--rest_framework/utils/field_mapping.py2
-rw-r--r--tests/accounts/__init__.py0
-rw-r--r--tests/accounts/models.py8
-rw-r--r--tests/accounts/serializers.py11
-rw-r--r--tests/conftest.py3
-rw-r--r--tests/put_as_create_workspace.txt33
-rw-r--r--tests/records/__init__.py0
-rw-r--r--tests/records/models.py6
-rw-r--r--tests/settings.py165
-rw-r--r--tests/test_model_serializer.py6
-rw-r--r--tests/test_permissions.py106
-rw-r--r--tests/test_serializer_import.py19
-rw-r--r--tests/users/__init__.py0
-rw-r--r--tests/users/models.py6
-rw-r--r--tests/users/serializers.py8
19 files changed, 130 insertions, 346 deletions
diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md
index d3da0607..885fc183 100644
--- a/docs/topics/3.0-announcement.md
+++ b/docs/topics/3.0-announcement.md
@@ -506,9 +506,9 @@ We now use the following:
REST framework now has more explicit and clear control over validating empty values for fields.
-Previously the meaning of the `required=False` keyword argument was underspecified. In practice its use meant that a field could either be not included in the input, or it could be included, but be `None`.
+Previously the meaning of the `required=False` keyword argument was underspecified. In practice its use meant that a field could either be not included in the input, or it could be included, but be `None` or the empty string.
-We now have a better separation, with separate `required` and `allow_none` arguments.
+We now have a better separation, with separate `required`, `allow_none` and `allow_blank` arguments.
The following set of arguments are used to control validation of empty values:
@@ -519,7 +519,7 @@ The following set of arguments are used to control validation of empty values:
Typically you'll want to use `required=False` if the corresponding model field has a default value, and additionally set either `allow_none=True` or `allow_blank=True` if required.
-The `default` argument is there if you need it, but you'll more typically want defaults to be set on model fields, rather than serializer fields.
+The `default` argument is also available and always implies that the field is not required to be in the input. It is unnecessary to use the `required` argument when a default is specified, and doing so will result in an error.
#### Coercing output types.
diff --git a/rest_framework/relations.py b/rest_framework/relations.py
index 48ddf41e..79c8057b 100644
--- a/rest_framework/relations.py
+++ b/rest_framework/relations.py
@@ -10,9 +10,17 @@ from django.utils.translation import ugettext_lazy as _
class PKOnlyObject(object):
+ """
+ This is a mock object, used for when we only need the pk of the object
+ instance, but still want to return an object with a .pk attribute,
+ in order to keep the same interface as a regular model instance.
+ """
def __init__(self, pk):
self.pk = pk
+
+# We assume that 'validators' are intended for the child serializer,
+# rather than the parent serializer.
MANY_RELATION_KWARGS = (
'read_only', 'write_only', 'required', 'default', 'initial', 'source',
'label', 'help_text', 'style', 'error_messages'
@@ -34,15 +42,19 @@ class RelatedField(Field):
def __new__(cls, *args, **kwargs):
# We override this method in order to automagically create
- # `ManyRelation` classes instead when `many=True` is set.
+ # `ManyRelatedField` classes instead when `many=True` is set.
if kwargs.pop('many', False):
- list_kwargs = {'child_relation': cls(*args, **kwargs)}
- for key in kwargs.keys():
- if key in MANY_RELATION_KWARGS:
- list_kwargs[key] = kwargs[key]
- return ManyRelation(**list_kwargs)
+ return cls.many_init(*args, **kwargs)
return super(RelatedField, cls).__new__(cls, *args, **kwargs)
+ @classmethod
+ def many_init(cls, *args, **kwargs):
+ list_kwargs = {'child_relation': cls(*args, **kwargs)}
+ for key in kwargs.keys():
+ if key in MANY_RELATION_KWARGS:
+ list_kwargs[key] = kwargs[key]
+ return ManyRelatedField(**list_kwargs)
+
def run_validation(self, data=empty):
# We force empty strings to None values for relational fields.
if data == '':
@@ -286,12 +298,12 @@ class SlugRelatedField(RelatedField):
return getattr(obj, self.slug_field)
-class ManyRelation(Field):
+class ManyRelatedField(Field):
"""
Relationships with `many=True` transparently get coerced into instead being
- a ManyRelation with a child relationship.
+ a ManyRelatedField with a child relationship.
- The `ManyRelation` class is responsible for handling iterating through
+ The `ManyRelatedField` class is responsible for handling iterating through
the values and passing each one to the child relationship.
You shouldn't need to be using this class directly yourself.
@@ -302,7 +314,7 @@ class ManyRelation(Field):
def __init__(self, child_relation=None, *args, **kwargs):
self.child_relation = child_relation
assert child_relation is not None, '`child_relation` is a required argument.'
- super(ManyRelation, self).__init__(*args, **kwargs)
+ super(ManyRelatedField, self).__init__(*args, **kwargs)
self.child_relation.bind(field_name='', parent=self)
def get_value(self, dictionary):
diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py
index b56f99db..eb04e81e 100644
--- a/rest_framework/renderers.py
+++ b/rest_framework/renderers.py
@@ -383,7 +383,10 @@ class HTMLFormRenderer(BaseRenderer):
serializers.MultipleChoiceField: {
'base_template': 'select_multiple.html', # Also valid: 'checkbox_multiple.html'
},
- serializers.ManyRelation: {
+ serializers.RelatedField: {
+ 'base_template': 'select.html', # Also valid: 'radio.html'
+ },
+ serializers.ManyRelatedField: {
'base_template': 'select_multiple.html', # Also valid: 'checkbox_multiple.html'
},
serializers.Serializer: {
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index d83367f4..70bba8ab 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -46,6 +46,9 @@ import warnings
from rest_framework.relations import * # NOQA
from rest_framework.fields import * # NOQA
+
+# We assume that 'validators' are intended for the child serializer,
+# rather than the parent serializer.
LIST_SERIALIZER_KWARGS = (
'read_only', 'write_only', 'required', 'default', 'initial', 'source',
'label', 'help_text', 'style', 'error_messages',
@@ -73,13 +76,25 @@ class BaseSerializer(Field):
# We override this method in order to automagically create
# `ListSerializer` classes instead when `many=True` is set.
if kwargs.pop('many', False):
- list_kwargs = {'child': cls(*args, **kwargs)}
- for key in kwargs.keys():
- if key in LIST_SERIALIZER_KWARGS:
- list_kwargs[key] = kwargs[key]
- return ListSerializer(*args, **list_kwargs)
+ return cls.many_init(*args, **kwargs)
return super(BaseSerializer, cls).__new__(cls, *args, **kwargs)
+ @classmethod
+ def many_init(cls, *args, **kwargs):
+ """
+ This method implements the creation of a `ListSerializer` parent
+ class when `many=True` is used. You can customize it if you need to
+ control which keyword arguments are passed to the parent, and
+ which are passed to the child.
+ """
+ child_serializer = cls(*args, **kwargs)
+ list_kwargs = {'child': child_serializer}
+ list_kwargs.update(dict([
+ (key, value) for key, value in kwargs.items()
+ if key in LIST_SERIALIZER_KWARGS
+ ]))
+ return ListSerializer(*args, **list_kwargs)
+
def to_internal_value(self, data):
raise NotImplementedError('`to_internal_value()` must be implemented.')
@@ -449,26 +464,39 @@ class ListSerializer(BaseSerializer):
serializer=self
)
+ def update(self, instance, validated_data):
+ raise NotImplementedError(
+ "Serializers with many=True do not support multiple update by "
+ "default, only multiple create. For updates it is unclear how to "
+ "deal with insertions and deletions. If you need to support "
+ "multiple update, use a `ListSerializer` class and override "
+ "`.update()` so you can specify the behavior exactly."
+ )
+
+ def create(self, validated_data):
+ return [
+ self.child.create(attrs) for attrs in validated_data
+ ]
+
def save(self, **kwargs):
"""
Save and return a list of object instances.
"""
- assert self.instance is None, (
- "Serializers do not support multiple update by default, only "
- "multiple create. For updates it is unclear how to deal with "
- "insertions and deletions. If you need to support multiple update, "
- "use a `ListSerializer` class and override `.save()` so you can "
- "specify the behavior exactly."
- )
-
validated_data = [
dict(list(attrs.items()) + list(kwargs.items()))
for attrs in self.validated_data
]
- self.instance = [
- self.child.create(attrs) for attrs in validated_data
- ]
+ if self.instance is not None:
+ self.instance = self.update(self.instance, validated_data)
+ assert self.instance is not None, (
+ '`update()` did not return an object instance.'
+ )
+ else:
+ self.instance = self.create(validated_data)
+ assert self.instance is not None, (
+ '`create()` did not return an object instance.'
+ )
return self.instance
diff --git a/rest_framework/utils/field_mapping.py b/rest_framework/utils/field_mapping.py
index 24639085..ce339971 100644
--- a/rest_framework/utils/field_mapping.py
+++ b/rest_framework/utils/field_mapping.py
@@ -88,7 +88,7 @@ def get_field_kwargs(field_name, model_field):
kwargs['read_only'] = True
return kwargs
- if model_field.has_default():
+ if model_field.has_default() or model_field.blank or model_field.null:
kwargs['required'] = False
if model_field.flatchoices:
diff --git a/tests/accounts/__init__.py b/tests/accounts/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/accounts/__init__.py
+++ /dev/null
diff --git a/tests/accounts/models.py b/tests/accounts/models.py
deleted file mode 100644
index 3bf4a0c3..00000000
--- a/tests/accounts/models.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from django.db import models
-
-from 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/tests/accounts/serializers.py b/tests/accounts/serializers.py
deleted file mode 100644
index 57a91b92..00000000
--- a/tests/accounts/serializers.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from rest_framework import serializers
-
-from tests.accounts.models import Account
-from tests.users.serializers import UserSerializer
-
-
-class AccountSerializer(serializers.ModelSerializer):
- admins = UserSerializer(many=True)
-
- class Meta:
- model = Account
diff --git a/tests/conftest.py b/tests/conftest.py
index 4b33e19c..31142eaf 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -33,9 +33,6 @@ def pytest_configure():
'rest_framework',
'rest_framework.authtoken',
'tests',
- 'tests.accounts',
- 'tests.records',
- 'tests.users',
),
PASSWORD_HASHERS=(
'django.contrib.auth.hashers.SHA1PasswordHasher',
diff --git a/tests/put_as_create_workspace.txt b/tests/put_as_create_workspace.txt
deleted file mode 100644
index 6bc5218e..00000000
--- a/tests/put_as_create_workspace.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-# From test_validation...
-
-class TestPreSaveValidationExclusions(TestCase):
- def test_pre_save_validation_exclusions(self):
- """
- Somewhat weird test case to ensure that we don't perform model
- validation on read only fields.
- """
- obj = ValidationModel.objects.create(blank_validated_field='')
- request = factory.put('/', {}, format='json')
- view = UpdateValidationModel().as_view()
- response = view(request, pk=obj.pk).render()
- self.assertEqual(response.status_code, status.HTTP_200_OK)
-
-
-# From test_permissions...
-
-class ModelPermissionsIntegrationTests(TestCase):
- def setUp(...):
- ...
-
- def test_has_put_as_create_permissions(self):
- # User only has update permissions - should be able to update an entity.
- request = factory.put('/1', {'text': 'foobar'}, format='json',
- HTTP_AUTHORIZATION=self.updateonly_credentials)
- response = instance_view(request, pk='1')
- self.assertEqual(response.status_code, status.HTTP_200_OK)
-
- # But if PUTing to a new entity, permission should be denied.
- request = factory.put('/2', {'text': 'foobar'}, format='json',
- HTTP_AUTHORIZATION=self.updateonly_credentials)
- response = instance_view(request, pk='2')
- self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
diff --git a/tests/records/__init__.py b/tests/records/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/records/__init__.py
+++ /dev/null
diff --git a/tests/records/models.py b/tests/records/models.py
deleted file mode 100644
index 76954807..00000000
--- a/tests/records/models.py
+++ /dev/null
@@ -1,6 +0,0 @@
-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/tests/settings.py b/tests/settings.py
deleted file mode 100644
index 91c9ed09..00000000
--- a/tests/settings.py
+++ /dev/null
@@ -1,165 +0,0 @@
-# Django settings for testproject project.
-
-DEBUG = True
-TEMPLATE_DEBUG = DEBUG
-DEBUG_PROPAGATE_EXCEPTIONS = True
-
-ALLOWED_HOSTS = ['*']
-
-ADMINS = (
- # ('Your Name', 'your_email@domain.com'),
-)
-
-MANAGERS = ADMINS
-
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
- 'NAME': 'sqlite.db', # Or path to database file if using sqlite3.
- 'USER': '', # Not used with sqlite3.
- 'PASSWORD': '', # Not used with sqlite3.
- 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
- 'PORT': '', # Set to empty string for default. Not used with sqlite3.
- }
-}
-
-CACHES = {
- 'default': {
- 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
- }
-}
-
-# Local time zone for this installation. Choices can be found here:
-# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
-# although not all choices may be available on all operating systems.
-# On Unix systems, a value of None will cause Django to use the same
-# timezone as the operating system.
-# If running in a Windows environment this must be set to the same as your
-# system time zone.
-TIME_ZONE = 'Europe/London'
-
-# Language code for this installation. All choices can be found here:
-# http://www.i18nguy.com/unicode/language-identifiers.html
-LANGUAGE_CODE = 'en-uk'
-
-SITE_ID = 1
-
-# If you set this to False, Django will make some optimizations so as not
-# to load the internationalization machinery.
-USE_I18N = True
-
-# If you set this to False, Django will not format dates, numbers and
-# calendars according to the current locale
-USE_L10N = True
-
-# Absolute filesystem path to the directory that will hold user-uploaded files.
-# Example: "/home/media/media.lawrence.com/"
-MEDIA_ROOT = ''
-
-# URL that handles the media served from MEDIA_ROOT. Make sure to use a
-# trailing slash if there is a path component (optional in other cases).
-# Examples: "http://media.lawrence.com", "http://example.com/media/"
-MEDIA_URL = ''
-
-# Make this unique, and don't share it with anybody.
-SECRET_KEY = 'u@x-aj9(hoh#rb-^ymf#g2jx_hp0vj7u5#b@ag1n^seu9e!%cy'
-
-# List of callables that know how to import templates from various sources.
-TEMPLATE_LOADERS = (
- 'django.template.loaders.filesystem.Loader',
- 'django.template.loaders.app_directories.Loader',
-)
-
-MIDDLEWARE_CLASSES = (
- 'django.middleware.common.CommonMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
-)
-
-ROOT_URLCONF = 'tests.urls'
-
-TEMPLATE_DIRS = (
- # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
- # Always use forward slashes, even on Windows.
- # Don't forget to use absolute paths, not relative paths.
-)
-
-INSTALLED_APPS = (
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.sites',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'rest_framework',
- 'rest_framework.authtoken',
- 'tests',
- 'tests.accounts',
- 'tests.records',
- 'tests.users',
-)
-
-# OAuth is optional and won't work if there is no oauth_provider & oauth2
-try:
- import oauth_provider # NOQA
- import oauth2 # NOQA
-except ImportError:
- pass
-else:
- INSTALLED_APPS += (
- 'oauth_provider',
- )
-
-try:
- import provider # NOQA
-except ImportError:
- pass
-else:
- INSTALLED_APPS += (
- 'provider',
- 'provider.oauth2',
- )
-
-# guardian is optional
-try:
- import guardian # NOQA
-except ImportError:
- pass
-else:
- ANONYMOUS_USER_ID = -1
- AUTHENTICATION_BACKENDS = (
- 'django.contrib.auth.backends.ModelBackend', # default
- 'guardian.backends.ObjectPermissionBackend',
- )
- INSTALLED_APPS += (
- 'guardian',
- )
-
-STATIC_URL = '/static/'
-
-PASSWORD_HASHERS = (
- 'django.contrib.auth.hashers.SHA1PasswordHasher',
- 'django.contrib.auth.hashers.PBKDF2PasswordHasher',
- 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
- 'django.contrib.auth.hashers.BCryptPasswordHasher',
- 'django.contrib.auth.hashers.MD5PasswordHasher',
- 'django.contrib.auth.hashers.CryptPasswordHasher',
-)
-
-AUTH_USER_MODEL = 'auth.User'
-
-import django
-
-if django.VERSION < (1, 3):
- INSTALLED_APPS += ('staticfiles',)
-
-
-# If we're running on the Jenkins server we want to archive the coverage reports as XML.
-import os
-if os.environ.get('HUDSON_URL', None):
- TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner'
- TEST_OUTPUT_VERBOSE = True
- TEST_OUTPUT_DESCRIPTIONS = True
- TEST_OUTPUT_DIR = 'xmlrunner'
diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py
index b8b621be..3aec0da0 100644
--- a/tests/test_model_serializer.py
+++ b/tests/test_model_serializer.py
@@ -90,7 +90,7 @@ class TestRegularFieldMappings(TestCase):
email_field = EmailField(max_length=100)
float_field = FloatField()
integer_field = IntegerField()
- null_boolean_field = NullBooleanField()
+ null_boolean_field = NullBooleanField(required=False)
positive_integer_field = IntegerField()
positive_small_integer_field = IntegerField()
slug_field = SlugField(max_length=100)
@@ -112,8 +112,8 @@ class TestRegularFieldMappings(TestCase):
id = IntegerField(label='ID', read_only=True)
value_limit_field = IntegerField(max_value=10, min_value=1)
length_limit_field = CharField(max_length=12, min_length=3)
- blank_field = CharField(allow_blank=True, max_length=10)
- null_field = IntegerField(allow_null=True)
+ blank_field = CharField(allow_blank=True, max_length=10, required=False)
+ null_field = IntegerField(allow_null=True, required=False)
default_field = IntegerField(required=False)
descriptive_field = IntegerField(help_text='Some help text', label='A label')
choices_field = ChoiceField(choices=[('red', 'Red'), ('blue', 'Blue'), ('green', 'Green')])
diff --git a/tests/test_permissions.py b/tests/test_permissions.py
index ac398f80..97bac33d 100644
--- a/tests/test_permissions.py
+++ b/tests/test_permissions.py
@@ -95,59 +95,59 @@ class ModelPermissionsIntegrationTests(TestCase):
response = instance_view(request, pk=1)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
- # def test_options_permitted(self):
- # request = factory.options(
- # '/',
- # HTTP_AUTHORIZATION=self.permitted_credentials
- # )
- # response = root_view(request, pk='1')
- # self.assertEqual(response.status_code, status.HTTP_200_OK)
- # self.assertIn('actions', response.data)
- # self.assertEqual(list(response.data['actions'].keys()), ['POST'])
-
- # request = factory.options(
- # '/1',
- # HTTP_AUTHORIZATION=self.permitted_credentials
- # )
- # response = instance_view(request, pk='1')
- # self.assertEqual(response.status_code, status.HTTP_200_OK)
- # self.assertIn('actions', response.data)
- # self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
-
- # def test_options_disallowed(self):
- # request = factory.options(
- # '/',
- # HTTP_AUTHORIZATION=self.disallowed_credentials
- # )
- # response = root_view(request, pk='1')
- # self.assertEqual(response.status_code, status.HTTP_200_OK)
- # self.assertNotIn('actions', response.data)
-
- # request = factory.options(
- # '/1',
- # HTTP_AUTHORIZATION=self.disallowed_credentials
- # )
- # response = instance_view(request, pk='1')
- # self.assertEqual(response.status_code, status.HTTP_200_OK)
- # self.assertNotIn('actions', response.data)
-
- # def test_options_updateonly(self):
- # request = factory.options(
- # '/',
- # HTTP_AUTHORIZATION=self.updateonly_credentials
- # )
- # response = root_view(request, pk='1')
- # self.assertEqual(response.status_code, status.HTTP_200_OK)
- # self.assertNotIn('actions', response.data)
-
- # request = factory.options(
- # '/1',
- # HTTP_AUTHORIZATION=self.updateonly_credentials
- # )
- # response = instance_view(request, pk='1')
- # self.assertEqual(response.status_code, status.HTTP_200_OK)
- # self.assertIn('actions', response.data)
- # self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
+ def test_options_permitted(self):
+ request = factory.options(
+ '/',
+ HTTP_AUTHORIZATION=self.permitted_credentials
+ )
+ response = root_view(request, pk='1')
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertIn('actions', response.data)
+ self.assertEqual(list(response.data['actions'].keys()), ['POST'])
+
+ request = factory.options(
+ '/1',
+ HTTP_AUTHORIZATION=self.permitted_credentials
+ )
+ response = instance_view(request, pk='1')
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertIn('actions', response.data)
+ self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
+
+ def test_options_disallowed(self):
+ request = factory.options(
+ '/',
+ HTTP_AUTHORIZATION=self.disallowed_credentials
+ )
+ response = root_view(request, pk='1')
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertNotIn('actions', response.data)
+
+ request = factory.options(
+ '/1',
+ HTTP_AUTHORIZATION=self.disallowed_credentials
+ )
+ response = instance_view(request, pk='1')
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertNotIn('actions', response.data)
+
+ def test_options_updateonly(self):
+ request = factory.options(
+ '/',
+ HTTP_AUTHORIZATION=self.updateonly_credentials
+ )
+ response = root_view(request, pk='1')
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertNotIn('actions', response.data)
+
+ request = factory.options(
+ '/1',
+ HTTP_AUTHORIZATION=self.updateonly_credentials
+ )
+ response = instance_view(request, pk='1')
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertIn('actions', response.data)
+ self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
class BasicPermModel(models.Model):
diff --git a/tests/test_serializer_import.py b/tests/test_serializer_import.py
deleted file mode 100644
index d029c3c5..00000000
--- a/tests/test_serializer_import.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# from django.test import TestCase
-
-# from rest_framework import serializers
-# from 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/tests/users/__init__.py b/tests/users/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/users/__init__.py
+++ /dev/null
diff --git a/tests/users/models.py b/tests/users/models.py
deleted file mode 100644
index 128bac90..00000000
--- a/tests/users/models.py
+++ /dev/null
@@ -1,6 +0,0 @@
-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/tests/users/serializers.py b/tests/users/serializers.py
deleted file mode 100644
index 4893ddb3..00000000
--- a/tests/users/serializers.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from rest_framework import serializers
-
-from tests.users.models import User
-
-
-class UserSerializer(serializers.ModelSerializer):
- class Meta:
- model = User