diff --git a/.travis.yml b/.travis.yml
index 9543cb4525..d77943dbf4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,6 @@ dist: xenial
 matrix:
     fast_finish: true
     include:
-      - { python: "2.7", env: DJANGO=1.11 }
 
       - { python: "3.4", env: DJANGO=1.11 }
       - { python: "3.4", env: DJANGO=2.0 }
@@ -25,9 +24,10 @@ matrix:
       - { python: "3.7", env: DJANGO=2.2 }
       - { python: "3.7", env: DJANGO=master }
 
-      - { python: "3.7", env: TOXENV=base }
-      - { python: "2.7", env: TOXENV=lint }
-      - { python: "2.7", env: TOXENV=docs }
+      - { python: "3.6", env: TOXENV=base }
+      - { python: "3.6", env: TOXENV=lint }
+      - { python: "3.6", env: TOXENV=docs }
+
 
       - python: "3.7"
         env: TOXENV=dist
diff --git a/README.md b/README.md
index 66079edf07..921f50c8a7 100644
--- a/README.md
+++ b/README.md
@@ -53,9 +53,10 @@ There is a live example API for testing purposes, [available here][sandbox].
 
 # Requirements
 
-* Python (2.7, 3.4, 3.5, 3.6, 3.7)
+* Python (3.4, 3.5, 3.6, 3.7)
 * Django (1.11, 2.0, 2.1, 2.2)
 
+
 We **highly recommend** and only officially support the latest patch release of
 each Python and Django series.
 
diff --git a/rest_framework/authentication.py b/rest_framework/authentication.py
index 25150d5255..ae009b7403 100644
--- a/rest_framework/authentication.py
+++ b/rest_framework/authentication.py
@@ -1,7 +1,6 @@
 """
 Provides various authentication policies.
 """
-from __future__ import unicode_literals
 
 import base64
 import binascii
@@ -33,7 +32,7 @@ def _reject(self, request, reason):
         return reason
 
 
-class BaseAuthentication(object):
+class BaseAuthentication:
     """
     All authentication classes should extend BaseAuthentication.
     """
diff --git a/rest_framework/authtoken/migrations/0001_initial.py b/rest_framework/authtoken/migrations/0001_initial.py
index 75780fedf2..6a46ccfffe 100644
--- a/rest_framework/authtoken/migrations/0001_initial.py
+++ b/rest_framework/authtoken/migrations/0001_initial.py
@@ -1,6 +1,3 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
 from django.conf import settings
 from django.db import migrations, models
 
diff --git a/rest_framework/authtoken/migrations/0002_auto_20160226_1747.py b/rest_framework/authtoken/migrations/0002_auto_20160226_1747.py
index 9f7e58e226..43119099a3 100644
--- a/rest_framework/authtoken/migrations/0002_auto_20160226_1747.py
+++ b/rest_framework/authtoken/migrations/0002_auto_20160226_1747.py
@@ -1,6 +1,3 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
 from django.conf import settings
 from django.db import migrations, models
 
diff --git a/rest_framework/authtoken/models.py b/rest_framework/authtoken/models.py
index 7e96eff93b..0ed02c4154 100644
--- a/rest_framework/authtoken/models.py
+++ b/rest_framework/authtoken/models.py
@@ -3,11 +3,9 @@
 
 from django.conf import settings
 from django.db import models
-from django.utils.encoding import python_2_unicode_compatible
 from django.utils.translation import ugettext_lazy as _
 
 
-@python_2_unicode_compatible
 class Token(models.Model):
     """
     The default authorization token model.
@@ -32,7 +30,7 @@ class Meta:
     def save(self, *args, **kwargs):
         if not self.key:
             self.key = self.generate_key()
-        return super(Token, self).save(*args, **kwargs)
+        return super().save(*args, **kwargs)
 
     def generate_key(self):
         return binascii.hexlify(os.urandom(20)).decode()
diff --git a/rest_framework/compat.py b/rest_framework/compat.py
index 9422e6ad56..9c78c288e8 100644
--- a/rest_framework/compat.py
+++ b/rest_framework/compat.py
@@ -3,22 +3,13 @@
 versions of Django/Python, and compatibility wrappers around optional packages.
 """
 
-from __future__ import unicode_literals
-
 import sys
+from collections.abc import Mapping, MutableMapping  # noqa
 
 from django.conf import settings
 from django.core import validators
-from django.utils import six
 from django.views.generic import View
 
-try:
-    # Python 3
-    from collections.abc import Mapping, MutableMapping   # noqa
-except ImportError:
-    # Python 2.7
-    from collections import Mapping, MutableMapping   # noqa
-
 try:
     from django.urls import (  # noqa
         URLPattern,
@@ -92,8 +83,7 @@ def make_url_resolver(regex, urlpatterns):
 def unicode_repr(instance):
     # Get the repr of an instance, but ensure it is a unicode string
     # on both python 3 (already the case) and 2 (not the case).
-    if six.PY2:
-        return repr(instance).decode('utf-8')
+
     return repr(instance)
 
 
@@ -101,8 +91,7 @@ def unicode_to_repr(value):
     # Coerce a unicode string to the correct repr return type, depending on
     # the Python version. We wrap all our `__repr__` implementations with
     # this and then use unicode throughout internally.
-    if six.PY2:
-        return value.encode('utf-8')
+
     return value
 
 
@@ -168,10 +157,7 @@ def is_guardian_installed():
     """
     django-guardian is optional and only imported if in INSTALLED_APPS.
     """
-    if six.PY2:
-        # Guardian 1.5.0, for Django 2.2 is NOT compatible with Python 2.7.
-        # Remove when dropping PY2.
-        return False
+
     return 'guardian' in settings.INSTALLED_APPS
 
 
@@ -284,17 +270,13 @@ def md_filter_add_syntax_highlight(md):
 
 # `separators` argument to `json.dumps()` differs between 2.x and 3.x
 # See: https://bugs.python.org/issue22767
-if six.PY3:
-    SHORT_SEPARATORS = (',', ':')
-    LONG_SEPARATORS = (', ', ': ')
-    INDENT_SEPARATORS = (',', ': ')
-else:
-    SHORT_SEPARATORS = (b',', b':')
-    LONG_SEPARATORS = (b', ', b': ')
-    INDENT_SEPARATORS = (b',', b': ')
+
+SHORT_SEPARATORS = (',', ':')
+LONG_SEPARATORS = (', ', ': ')
+INDENT_SEPARATORS = (',', ': ')
 
 
-class CustomValidatorMessage(object):
+class CustomValidatorMessage:
     """
     We need to avoid evaluation of `lazy` translated `message` in `django.core.validators.BaseValidator.__init__`.
     https://github.com/django/django/blob/75ed5900321d170debef4ac452b8b3cf8a1c2384/django/core/validators.py#L297
@@ -304,7 +286,7 @@ class CustomValidatorMessage(object):
 
     def __init__(self, *args, **kwargs):
         self.message = kwargs.pop('message', self.message)
-        super(CustomValidatorMessage, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
 
 class MinValueValidator(CustomValidatorMessage, validators.MinValueValidator):
diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py
index 30bfcc4e53..537c995b2d 100644
--- a/rest_framework/decorators.py
+++ b/rest_framework/decorators.py
@@ -6,7 +6,6 @@
 based views, as well as the `@detail_route` and `@list_route` decorators, which are
 used to annotate methods on viewsets that should be included by routers.
 """
-from __future__ import unicode_literals
 
 import types
 import warnings
diff --git a/rest_framework/exceptions.py b/rest_framework/exceptions.py
index f79b161294..b67e20fccf 100644
--- a/rest_framework/exceptions.py
+++ b/rest_framework/exceptions.py
@@ -4,7 +4,6 @@
 In addition Django's built in 403 and 404 exceptions are handled.
 (`django.http.Http404` and `django.core.exceptions.PermissionDenied`)
 """
-from __future__ import unicode_literals
 
 import math
 
@@ -76,7 +75,7 @@ def __new__(cls, string, code=None):
         return self
 
     def __eq__(self, other):
-        r = super(ErrorDetail, self).__eq__(other)
+        r = super().__eq__(other)
         try:
             return r and self.code == other.code
         except AttributeError:
@@ -196,7 +195,7 @@ class MethodNotAllowed(APIException):
     def __init__(self, method, detail=None, code=None):
         if detail is None:
             detail = force_text(self.default_detail).format(method=method)
-        super(MethodNotAllowed, self).__init__(detail, code)
+        super().__init__(detail, code)
 
 
 class NotAcceptable(APIException):
@@ -206,7 +205,7 @@ class NotAcceptable(APIException):
 
     def __init__(self, detail=None, code=None, available_renderers=None):
         self.available_renderers = available_renderers
-        super(NotAcceptable, self).__init__(detail, code)
+        super().__init__(detail, code)
 
 
 class UnsupportedMediaType(APIException):
@@ -217,7 +216,7 @@ class UnsupportedMediaType(APIException):
     def __init__(self, media_type, detail=None, code=None):
         if detail is None:
             detail = force_text(self.default_detail).format(media_type=media_type)
-        super(UnsupportedMediaType, self).__init__(detail, code)
+        super().__init__(detail, code)
 
 
 class Throttled(APIException):
@@ -238,7 +237,7 @@ def __init__(self, wait=None, detail=None, code=None):
                                      self.extra_detail_plural.format(wait=wait),
                                      wait))))
         self.wait = wait
-        super(Throttled, self).__init__(detail, code)
+        super().__init__(detail, code)
 
 
 def server_error(request, *args, **kwargs):
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index c8f65db0e5..c14a5a223b 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import copy
 import datetime
 import decimal
@@ -185,18 +183,18 @@ def iter_options(grouped_choices, cutoff=None, cutoff_text=None):
     """
     Helper function for options and option groups in templates.
     """
-    class StartOptionGroup(object):
+    class StartOptionGroup:
         start_option_group = True
         end_option_group = False
 
         def __init__(self, label):
             self.label = label
 
-    class EndOptionGroup(object):
+    class EndOptionGroup:
         start_option_group = False
         end_option_group = True
 
-    class Option(object):
+    class Option:
         start_option_group = False
         end_option_group = False
 
@@ -251,7 +249,7 @@ def get_error_detail(exc_info):
     }
 
 
-class CreateOnlyDefault(object):
+class CreateOnlyDefault:
     """
     This class may be used to provide default values that are only used
     for create operations, but that do not return any value for update
@@ -278,7 +276,7 @@ def __repr__(self):
         )
 
 
-class CurrentUserDefault(object):
+class CurrentUserDefault:
     def set_context(self, serializer_field):
         self.user = serializer_field.context['request'].user
 
@@ -305,7 +303,7 @@ class SkipField(Exception):
 )
 
 
-class Field(object):
+class Field:
     _creation_counter = 0
 
     default_error_messages = {
@@ -724,7 +722,7 @@ class NullBooleanField(Field):
     def __init__(self, **kwargs):
         assert 'allow_null' not in kwargs, '`allow_null` is not a valid option.'
         kwargs['allow_null'] = True
-        super(NullBooleanField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
     def to_internal_value(self, data):
         try:
@@ -764,7 +762,7 @@ def __init__(self, **kwargs):
         self.trim_whitespace = kwargs.pop('trim_whitespace', True)
         self.max_length = kwargs.pop('max_length', None)
         self.min_length = kwargs.pop('min_length', None)
-        super(CharField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         if self.max_length is not None:
             message = lazy(
                 self.error_messages['max_length'].format,
@@ -790,7 +788,7 @@ def run_validation(self, data=empty):
             if not self.allow_blank:
                 self.fail('blank')
             return ''
-        return super(CharField, self).run_validation(data)
+        return super().run_validation(data)
 
     def to_internal_value(self, data):
         # We're lenient with allowing basic numerics to be coerced into strings,
@@ -811,7 +809,7 @@ class EmailField(CharField):
     }
 
     def __init__(self, **kwargs):
-        super(EmailField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         validator = EmailValidator(message=self.error_messages['invalid'])
         self.validators.append(validator)
 
@@ -822,7 +820,7 @@ class RegexField(CharField):
     }
 
     def __init__(self, regex, **kwargs):
-        super(RegexField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         validator = RegexValidator(regex, message=self.error_messages['invalid'])
         self.validators.append(validator)
 
@@ -834,7 +832,7 @@ class SlugField(CharField):
     }
 
     def __init__(self, allow_unicode=False, **kwargs):
-        super(SlugField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         self.allow_unicode = allow_unicode
         if self.allow_unicode:
             validator = RegexValidator(re.compile(r'^[-\w]+\Z', re.UNICODE), message=self.error_messages['invalid_unicode'])
@@ -849,7 +847,7 @@ class URLField(CharField):
     }
 
     def __init__(self, **kwargs):
-        super(URLField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         validator = URLValidator(message=self.error_messages['invalid'])
         self.validators.append(validator)
 
@@ -868,7 +866,7 @@ def __init__(self, **kwargs):
                 'Invalid format for uuid representation. '
                 'Must be one of "{0}"'.format('", "'.join(self.valid_formats))
             )
-        super(UUIDField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
     def to_internal_value(self, data):
         if not isinstance(data, uuid.UUID):
@@ -900,7 +898,7 @@ class IPAddressField(CharField):
     def __init__(self, protocol='both', **kwargs):
         self.protocol = protocol.lower()
         self.unpack_ipv4 = (self.protocol == 'both')
-        super(IPAddressField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         validators, error_message = ip_address_validators(protocol, self.unpack_ipv4)
         self.validators.extend(validators)
 
@@ -915,7 +913,7 @@ def to_internal_value(self, data):
             except DjangoValidationError:
                 self.fail('invalid', value=data)
 
-        return super(IPAddressField, self).to_internal_value(data)
+        return super().to_internal_value(data)
 
 
 # Number types...
@@ -933,7 +931,7 @@ class IntegerField(Field):
     def __init__(self, **kwargs):
         self.max_value = kwargs.pop('max_value', None)
         self.min_value = kwargs.pop('min_value', None)
-        super(IntegerField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         if self.max_value is not None:
             message = lazy(
                 self.error_messages['max_value'].format,
@@ -973,7 +971,7 @@ class FloatField(Field):
     def __init__(self, **kwargs):
         self.max_value = kwargs.pop('max_value', None)
         self.min_value = kwargs.pop('min_value', None)
-        super(FloatField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         if self.max_value is not None:
             message = lazy(
                 self.error_messages['max_value'].format,
@@ -1031,7 +1029,7 @@ def __init__(self, max_digits, decimal_places, coerce_to_string=None, max_value=
         else:
             self.max_whole_digits = None
 
-        super(DecimalField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
         if self.max_value is not None:
             message = lazy(
@@ -1167,7 +1165,7 @@ def __init__(self, format=empty, input_formats=None, default_timezone=None, *arg
             self.input_formats = input_formats
         if default_timezone is not None:
             self.timezone = default_timezone
-        super(DateTimeField, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def enforce_timezone(self, value):
         """
@@ -1251,7 +1249,7 @@ def __init__(self, format=empty, input_formats=None, *args, **kwargs):
             self.format = format
         if input_formats is not None:
             self.input_formats = input_formats
-        super(DateField, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def to_internal_value(self, value):
         input_formats = getattr(self, 'input_formats', api_settings.DATE_INPUT_FORMATS)
@@ -1317,7 +1315,7 @@ def __init__(self, format=empty, input_formats=None, *args, **kwargs):
             self.format = format
         if input_formats is not None:
             self.input_formats = input_formats
-        super(TimeField, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def to_internal_value(self, value):
         input_formats = getattr(self, 'input_formats', api_settings.TIME_INPUT_FORMATS)
@@ -1378,7 +1376,7 @@ class DurationField(Field):
     def __init__(self, **kwargs):
         self.max_value = kwargs.pop('max_value', None)
         self.min_value = kwargs.pop('min_value', None)
-        super(DurationField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         if self.max_value is not None:
             message = lazy(
                 self.error_messages['max_value'].format,
@@ -1420,7 +1418,7 @@ def __init__(self, choices, **kwargs):
 
         self.allow_blank = kwargs.pop('allow_blank', False)
 
-        super(ChoiceField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
     def to_internal_value(self, data):
         if data == '' and self.allow_blank:
@@ -1473,7 +1471,7 @@ class MultipleChoiceField(ChoiceField):
 
     def __init__(self, *args, **kwargs):
         self.allow_empty = kwargs.pop('allow_empty', True)
-        super(MultipleChoiceField, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def get_value(self, dictionary):
         if self.field_name not in dictionary:
@@ -1516,7 +1514,7 @@ def __init__(self, path, match=None, recursive=False, allow_files=True,
             allow_folders=allow_folders, required=required
         )
         kwargs['choices'] = field.choices
-        super(FilePathField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
 
 # File types...
@@ -1535,7 +1533,7 @@ def __init__(self, *args, **kwargs):
         self.allow_empty_file = kwargs.pop('allow_empty_file', False)
         if 'use_url' in kwargs:
             self.use_url = kwargs.pop('use_url')
-        super(FileField, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def to_internal_value(self, data):
         try:
@@ -1581,13 +1579,13 @@ class ImageField(FileField):
 
     def __init__(self, *args, **kwargs):
         self._DjangoImageField = kwargs.pop('_DjangoImageField', DjangoImageField)
-        super(ImageField, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def to_internal_value(self, data):
         # Image validation is a bit grungy, so we'll just outright
         # defer to Django's implementation so we don't need to
         # consider it, or treat PIL as a test dependency.
-        file_object = super(ImageField, self).to_internal_value(data)
+        file_object = super().to_internal_value(data)
         django_field = self._DjangoImageField()
         django_field.error_messages = self.error_messages
         return django_field.clean(file_object)
@@ -1597,7 +1595,7 @@ def to_internal_value(self, data):
 
 class _UnvalidatedField(Field):
     def __init__(self, *args, **kwargs):
-        super(_UnvalidatedField, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self.allow_blank = True
         self.allow_null = True
 
@@ -1630,7 +1628,7 @@ def __init__(self, *args, **kwargs):
             "Remove `source=` from the field declaration."
         )
 
-        super(ListField, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self.child.bind(field_name='', parent=self)
         if self.max_length is not None:
             message = self.error_messages['max_length'].format(max_length=self.max_length)
@@ -1703,7 +1701,7 @@ def __init__(self, *args, **kwargs):
             "Remove `source=` from the field declaration."
         )
 
-        super(DictField, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self.child.bind(field_name='', parent=self)
 
     def get_value(self, dictionary):
@@ -1750,7 +1748,7 @@ class HStoreField(DictField):
     child = CharField(allow_blank=True, allow_null=True)
 
     def __init__(self, *args, **kwargs):
-        super(HStoreField, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         assert isinstance(self.child, CharField), (
             "The `child` argument must be an instance of `CharField`, "
             "as the hstore extension stores values as strings."
@@ -1764,7 +1762,7 @@ class JSONField(Field):
 
     def __init__(self, *args, **kwargs):
         self.binary = kwargs.pop('binary', False)
-        super(JSONField, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def get_value(self, dictionary):
         if html.is_html_input(dictionary) and self.field_name in dictionary:
@@ -1817,7 +1815,7 @@ class ExampleSerializer(Serializer):
 
     def __init__(self, **kwargs):
         kwargs['read_only'] = True
-        super(ReadOnlyField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
     def to_representation(self, value):
         return value
@@ -1834,7 +1832,7 @@ class HiddenField(Field):
     def __init__(self, **kwargs):
         assert 'default' in kwargs, 'default is a required argument.'
         kwargs['write_only'] = True
-        super(HiddenField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
     def get_value(self, dictionary):
         # We always use the default value for `HiddenField`.
@@ -1864,7 +1862,7 @@ def __init__(self, method_name=None, **kwargs):
         self.method_name = method_name
         kwargs['source'] = '*'
         kwargs['read_only'] = True
-        super(SerializerMethodField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
     def bind(self, field_name, parent):
         # In order to enforce a consistent style, we error if a redundant
@@ -1882,7 +1880,7 @@ def bind(self, field_name, parent):
         if self.method_name is None:
             self.method_name = default_method_name
 
-        super(SerializerMethodField, self).bind(field_name, parent)
+        super().bind(field_name, parent)
 
     def to_representation(self, value):
         method = getattr(self.parent, self.method_name)
@@ -1905,7 +1903,7 @@ def __init__(self, model_field, **kwargs):
         # The `max_length` option is supported by Django's base `Field` class,
         # so we'd better support it here.
         max_length = kwargs.pop('max_length', None)
-        super(ModelField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         if max_length is not None:
             message = lazy(
                 self.error_messages['max_length'].format,
diff --git a/rest_framework/filters.py b/rest_framework/filters.py
index bb1b86586c..5b1f389ac1 100644
--- a/rest_framework/filters.py
+++ b/rest_framework/filters.py
@@ -2,7 +2,6 @@
 Provides generic filtering backends that can be used to filter the results
 returned by list views.
 """
-from __future__ import unicode_literals
 
 import operator
 import warnings
@@ -24,7 +23,7 @@
 from rest_framework.settings import api_settings
 
 
-class BaseFilterBackend(object):
+class BaseFilterBackend:
     """
     A base class from which all filter backend classes should inherit.
     """
diff --git a/rest_framework/generics.py b/rest_framework/generics.py
index 8d0bf284a9..2034827c1b 100644
--- a/rest_framework/generics.py
+++ b/rest_framework/generics.py
@@ -1,7 +1,6 @@
 """
 Generic views that provide commonly needed behaviour.
 """
-from __future__ import unicode_literals
 
 from django.core.exceptions import ValidationError
 from django.db.models.query import QuerySet
diff --git a/rest_framework/metadata.py b/rest_framework/metadata.py
index 9f93244693..a68ac7ef25 100644
--- a/rest_framework/metadata.py
+++ b/rest_framework/metadata.py
@@ -6,7 +6,6 @@
 Future implementations might use JSON schema or other definitions in order
 to return this information in a more standardized way.
 """
-from __future__ import unicode_literals
 
 from collections import OrderedDict
 
@@ -19,7 +18,7 @@
 from rest_framework.utils.field_mapping import ClassLookupDict
 
 
-class BaseMetadata(object):
+class BaseMetadata:
     def determine_metadata(self, request, view):
         """
         Return a dictionary of metadata about the view.
diff --git a/rest_framework/mixins.py b/rest_framework/mixins.py
index de10d69308..ff21d790fc 100644
--- a/rest_framework/mixins.py
+++ b/rest_framework/mixins.py
@@ -4,14 +4,13 @@
 We don't bind behaviour to http method handlers yet,
 which allows mixin classes to be composed in interesting ways.
 """
-from __future__ import unicode_literals
 
 from rest_framework import status
 from rest_framework.response import Response
 from rest_framework.settings import api_settings
 
 
-class CreateModelMixin(object):
+class CreateModelMixin:
     """
     Create a model instance.
     """
@@ -32,7 +31,7 @@ def get_success_headers(self, data):
             return {}
 
 
-class ListModelMixin(object):
+class ListModelMixin:
     """
     List a queryset.
     """
@@ -48,7 +47,7 @@ def list(self, request, *args, **kwargs):
         return Response(serializer.data)
 
 
-class RetrieveModelMixin(object):
+class RetrieveModelMixin:
     """
     Retrieve a model instance.
     """
@@ -58,7 +57,7 @@ def retrieve(self, request, *args, **kwargs):
         return Response(serializer.data)
 
 
-class UpdateModelMixin(object):
+class UpdateModelMixin:
     """
     Update a model instance.
     """
@@ -84,7 +83,7 @@ def partial_update(self, request, *args, **kwargs):
         return self.update(request, *args, **kwargs)
 
 
-class DestroyModelMixin(object):
+class DestroyModelMixin:
     """
     Destroy a model instance.
     """
diff --git a/rest_framework/negotiation.py b/rest_framework/negotiation.py
index ca1b59f12e..7d80ba12d8 100644
--- a/rest_framework/negotiation.py
+++ b/rest_framework/negotiation.py
@@ -2,7 +2,6 @@
 Content negotiation deals with selecting an appropriate renderer given the
 incoming request.  Typically this will be based on the request's Accept header.
 """
-from __future__ import unicode_literals
 
 from django.http import Http404
 
@@ -13,7 +12,7 @@
 )
 
 
-class BaseContentNegotiation(object):
+class BaseContentNegotiation:
     def select_parser(self, request, parsers):
         raise NotImplementedError('.select_parser() must be implemented')
 
diff --git a/rest_framework/pagination.py b/rest_framework/pagination.py
index b11d7cdf3a..d593944333 100644
--- a/rest_framework/pagination.py
+++ b/rest_framework/pagination.py
@@ -3,7 +3,6 @@
 Pagination serializers determine the structure of the output that should
 be used for paginated responses.
 """
-from __future__ import unicode_literals
 
 from base64 import b64decode, b64encode
 from collections import OrderedDict, namedtuple
@@ -133,7 +132,7 @@ def invert(x):
 PAGE_BREAK = PageLink(url=None, number=None, is_active=False, is_break=True)
 
 
-class BasePagination(object):
+class BasePagination:
     display_page_controls = False
 
     def paginate_queryset(self, queryset, request, view=None):  # pragma: no cover
diff --git a/rest_framework/parsers.py b/rest_framework/parsers.py
index 35d0d1aa70..d20c6071bd 100644
--- a/rest_framework/parsers.py
+++ b/rest_framework/parsers.py
@@ -4,7 +4,6 @@
 They give us a generic way of being able to handle various media types
 on the request, such as form content or json encoded data.
 """
-from __future__ import unicode_literals
 
 import codecs
 
@@ -25,13 +24,13 @@
 from rest_framework.utils import json
 
 
-class DataAndFiles(object):
+class DataAndFiles:
     def __init__(self, data, files):
         self.data = data
         self.files = files
 
 
-class BaseParser(object):
+class BaseParser:
     """
     All parsers should extend `BaseParser`, specifying a `media_type`
     attribute, and overriding the `.parse()` method.
diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py
index 5d75f54bad..7f374d561f 100644
--- a/rest_framework/permissions.py
+++ b/rest_framework/permissions.py
@@ -1,7 +1,6 @@
 """
 Provides a set of pluggable permission policies.
 """
-from __future__ import unicode_literals
 
 from django.http import Http404
 from django.utils import six
diff --git a/rest_framework/relations.py b/rest_framework/relations.py
index 31c1e75618..27e29676d2 100644
--- a/rest_framework/relations.py
+++ b/rest_framework/relations.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import sys
 from collections import OrderedDict
 
@@ -9,9 +6,7 @@
 from django.db.models.query import QuerySet
 from django.urls import NoReverseMatch, Resolver404, get_script_prefix, resolve
 from django.utils import six
-from django.utils.encoding import (
-    python_2_unicode_compatible, smart_text, uri_to_iri
-)
+from django.utils.encoding import smart_text, uri_to_iri
 from django.utils.six.moves.urllib import parse as urlparse
 from django.utils.translation import ugettext_lazy as _
 
@@ -70,8 +65,7 @@ def name(self):
     is_hyperlink = True
 
 
-@python_2_unicode_compatible
-class PKOnlyObject(object):
+class PKOnlyObject:
     """
     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,
@@ -121,7 +115,7 @@ def __init__(self, **kwargs):
         )
         kwargs.pop('many', None)
         kwargs.pop('allow_empty', None)
-        super(RelatedField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
     def __new__(cls, *args, **kwargs):
         # We override this method in order to automagically create
@@ -157,7 +151,7 @@ def run_validation(self, data=empty):
         # We force empty strings to None values for relational fields.
         if data == '':
             data = None
-        return super(RelatedField, self).run_validation(data)
+        return super().run_validation(data)
 
     def get_queryset(self):
         queryset = self.queryset
@@ -189,7 +183,7 @@ def get_attribute(self, instance):
                 pass
 
         # Standard case, return the object instance.
-        return super(RelatedField, self).get_attribute(instance)
+        return super().get_attribute(instance)
 
     def get_choices(self, cutoff=None):
         queryset = self.get_queryset()
@@ -236,7 +230,7 @@ class StringRelatedField(RelatedField):
 
     def __init__(self, **kwargs):
         kwargs['read_only'] = True
-        super(StringRelatedField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
     def to_representation(self, value):
         return six.text_type(value)
@@ -251,7 +245,7 @@ class PrimaryKeyRelatedField(RelatedField):
 
     def __init__(self, **kwargs):
         self.pk_field = kwargs.pop('pk_field', None)
-        super(PrimaryKeyRelatedField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
     def use_pk_only_optimization(self):
         return True
@@ -297,7 +291,7 @@ def __init__(self, view_name=None, **kwargs):
         # implicit `self` argument to be passed.
         self.reverse = reverse
 
-        super(HyperlinkedRelatedField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
     def use_pk_only_optimization(self):
         return self.lookup_field == 'pk'
@@ -432,7 +426,7 @@ def __init__(self, view_name=None, **kwargs):
         assert view_name is not None, 'The `view_name` argument is required.'
         kwargs['read_only'] = True
         kwargs['source'] = '*'
-        super(HyperlinkedIdentityField, self).__init__(view_name, **kwargs)
+        super().__init__(view_name, **kwargs)
 
     def use_pk_only_optimization(self):
         # We have the complete object instance already. We don't need
@@ -453,7 +447,7 @@ class SlugRelatedField(RelatedField):
     def __init__(self, slug_field=None, **kwargs):
         assert slug_field is not None, 'The `slug_field` argument is required.'
         self.slug_field = slug_field
-        super(SlugRelatedField, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
     def to_internal_value(self, data):
         try:
@@ -502,7 +496,7 @@ def __init__(self, child_relation=None, *args, **kwargs):
             self.html_cutoff_text or _(api_settings.HTML_SELECT_CUTOFF_TEXT)
         )
         assert child_relation is not None, '`child_relation` is a required argument.'
-        super(ManyRelatedField, self).__init__(*args, **kwargs)
+        super().__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 f043e63278..15b4c6d009 100644
--- a/rest_framework/renderers.py
+++ b/rest_framework/renderers.py
@@ -6,7 +6,6 @@
 
 REST framework also provides an HTML renderer that renders the browsable API.
 """
-from __future__ import unicode_literals
 
 import base64
 from collections import OrderedDict
@@ -40,7 +39,7 @@ def zero_as_none(value):
     return None if value == 0 else value
 
 
-class BaseRenderer(object):
+class BaseRenderer:
     """
     All renderers should extend this class, setting the `media_type`
     and `format` attributes, and override the `.render()` method.
@@ -791,7 +790,7 @@ def get_context(self, data, accepted_media_type, renderer_context):
         """
         Render the HTML for the browsable API representation.
         """
-        context = super(AdminRenderer, self).get_context(
+        context = super().get_context(
             data, accepted_media_type, renderer_context
         )
 
diff --git a/rest_framework/request.py b/rest_framework/request.py
index a6d92e2bdc..e167058307 100644
--- a/rest_framework/request.py
+++ b/rest_framework/request.py
@@ -8,7 +8,6 @@
     - full support of PUT method, including support for file uploads
     - form overloading of HTTP method, content type and content
 """
-from __future__ import unicode_literals
 
 import io
 import sys
@@ -34,7 +33,7 @@ def is_form_media_type(media_type):
             base_media_type == 'multipart/form-data')
 
 
-class override_method(object):
+class override_method:
     """
     A context manager that temporarily overrides the method on a request,
     additionally setting the `view.request` attribute.
@@ -81,7 +80,7 @@ def wrap_attributeerrors():
         six.reraise(type(exc), exc, info[2])
 
 
-class Empty(object):
+class Empty:
     """
     Placeholder for unset attributes.
     Cannot use `None`, as that may be a valid value.
@@ -126,7 +125,7 @@ def clone_request(request, method):
     return ret
 
 
-class ForcedAuthentication(object):
+class ForcedAuthentication:
     """
     This authentication class is used if the test client or request factory
     forcibly authenticated the request.
@@ -140,7 +139,7 @@ def authenticate(self, request):
         return (self.force_user, self.force_token)
 
 
-class Request(object):
+class Request:
     """
     Wrapper allowing to enhance a standard `HttpRequest` instance.
 
diff --git a/rest_framework/response.py b/rest_framework/response.py
index bf06632557..1285738c5b 100644
--- a/rest_framework/response.py
+++ b/rest_framework/response.py
@@ -4,7 +4,6 @@
 
 The appropriate renderer is called during Django's template response rendering.
 """
-from __future__ import unicode_literals
 
 from django.template.response import SimpleTemplateResponse
 from django.utils import six
@@ -29,7 +28,7 @@ def __init__(self, data=None, status=None,
         Setting 'renderer' and 'media_type' will typically be deferred,
         For example being set automatically by the `APIView`.
         """
-        super(Response, self).__init__(None, status=status)
+        super().__init__(None, status=status)
 
         if isinstance(data, Serializer):
             msg = (
@@ -94,7 +93,7 @@ def __getstate__(self):
         """
         Remove attributes from the response that shouldn't be cached.
         """
-        state = super(Response, self).__getstate__()
+        state = super().__getstate__()
         for key in (
             'accepted_renderer', 'renderer_context', 'resolver_match',
             'client', 'request', 'json', 'wsgi_request'
diff --git a/rest_framework/reverse.py b/rest_framework/reverse.py
index e9cf737f19..1e0d8b43d3 100644
--- a/rest_framework/reverse.py
+++ b/rest_framework/reverse.py
@@ -1,7 +1,6 @@
 """
 Provide urlresolver functions that return fully qualified URLs or view names
 """
-from __future__ import unicode_literals
 
 from django.urls import NoReverseMatch
 from django.urls import reverse as django_reverse
diff --git a/rest_framework/routers.py b/rest_framework/routers.py
index 1cacea1812..50918f9416 100644
--- a/rest_framework/routers.py
+++ b/rest_framework/routers.py
@@ -13,7 +13,6 @@
 
     urlpatterns = router.urls
 """
-from __future__ import unicode_literals
 
 import itertools
 import warnings
@@ -39,7 +38,7 @@
 DynamicRoute = namedtuple('DynamicRoute', ['url', 'name', 'detail', 'initkwargs'])
 
 
-class DynamicDetailRoute(object):
+class DynamicDetailRoute:
     def __new__(cls, url, name, initkwargs):
         warnings.warn(
             "`DynamicDetailRoute` is deprecated and will be removed in 3.10 "
@@ -50,7 +49,7 @@ def __new__(cls, url, name, initkwargs):
         return DynamicRoute(url, name, True, initkwargs)
 
 
-class DynamicListRoute(object):
+class DynamicListRoute:
     def __new__(cls, url, name, initkwargs):
         warnings.warn(
             "`DynamicListRoute` is deprecated and will be removed in 3.10 in "
@@ -173,7 +172,7 @@ class SimpleRouter(BaseRouter):
 
     def __init__(self, trailing_slash=True):
         self.trailing_slash = '/' if trailing_slash else ''
-        super(SimpleRouter, self).__init__()
+        super().__init__()
 
     def get_default_basename(self, viewset):
         """
@@ -365,7 +364,7 @@ def __init__(self, *args, **kwargs):
             self.root_renderers = kwargs.pop('root_renderers')
         else:
             self.root_renderers = list(api_settings.DEFAULT_RENDERER_CLASSES)
-        super(DefaultRouter, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def get_api_root_view(self, api_urls=None):
         """
@@ -383,7 +382,7 @@ def get_urls(self):
         Generate the list of URL patterns, including a default root view
         for the API, and appending `.json` style format suffixes.
         """
-        urls = super(DefaultRouter, self).get_urls()
+        urls = super().get_urls()
 
         if self.include_root_view:
             view = self.get_api_root_view(api_urls=urls)
diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py
index db226a6c16..5073daf040 100644
--- a/rest_framework/schemas/generators.py
+++ b/rest_framework/schemas/generators.py
@@ -68,7 +68,7 @@ class LinkNode(OrderedDict):
     def __init__(self):
         self.links = []
         self.methods_counter = Counter()
-        super(LinkNode, self).__init__()
+        super().__init__()
 
     def get_available_key(self, preferred_key):
         if preferred_key not in self:
@@ -140,7 +140,7 @@ def endpoint_ordering(endpoint):
 )
 
 
-class EndpointEnumerator(object):
+class EndpointEnumerator:
     """
     A class to determine the available API endpoints that a project exposes.
     """
@@ -232,7 +232,7 @@ def get_allowed_methods(self, callback):
         return [method for method in methods if method not in ('OPTIONS', 'HEAD')]
 
 
-class SchemaGenerator(object):
+class SchemaGenerator:
     # Map HTTP methods onto actions.
     default_mapping = {
         'get': 'retrieve',
diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py
index 85142edce4..56b04d8df7 100644
--- a/rest_framework/schemas/inspectors.py
+++ b/rest_framework/schemas/inspectors.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 """
 inspectors.py   # Per-endpoint view introspection
 
@@ -125,7 +124,7 @@ def get_pk_description(model, model_field):
     )
 
 
-class ViewInspector(object):
+class ViewInspector:
     """
     Descriptor class on APIView.
 
@@ -207,7 +206,7 @@ def __init__(self, manual_fields=None):
         * `manual_fields`: list of `coreapi.Field` instances that
             will be added to auto-generated fields, overwriting on `Field.name`
         """
-        super(AutoSchema, self).__init__()
+        super().__init__()
         if manual_fields is None:
             manual_fields = []
         self._manual_fields = manual_fields
@@ -475,7 +474,7 @@ def __init__(self, fields, description='', encoding=None):
         * `fields`: list of `coreapi.Field` instances.
         * `description`: String description for view. Optional.
         """
-        super(ManualSchema, self).__init__()
+        super().__init__()
         assert all(isinstance(f, coreapi.Field) for f in fields), "`fields` must be a list of coreapi.Field instances"
         self._fields = fields
         self._description = description
@@ -498,7 +497,7 @@ def get_link(self, path, method, base_url):
 class DefaultSchema(ViewInspector):
     """Allows overriding AutoSchema using DEFAULT_SCHEMA_CLASS setting"""
     def __get__(self, instance, owner):
-        result = super(DefaultSchema, self).__get__(instance, owner)
+        result = super().__get__(instance, owner)
         if not isinstance(result, DefaultSchema):
             return result
 
diff --git a/rest_framework/schemas/views.py b/rest_framework/schemas/views.py
index f5e327a941..73b4a80718 100644
--- a/rest_framework/schemas/views.py
+++ b/rest_framework/schemas/views.py
@@ -17,7 +17,7 @@ class SchemaView(APIView):
     public = False
 
     def __init__(self, *args, **kwargs):
-        super(SchemaView, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         if self.renderer_classes is None:
             self.renderer_classes = [
                 renderers.OpenAPIRenderer,
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 9830edb3f0..a50c91eb0f 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -10,7 +10,6 @@
 2. The process of marshalling between python primitives and request and
 response content is handled by parsers and renderers.
 """
-from __future__ import unicode_literals
 
 import copy
 import inspect
diff --git a/rest_framework/settings.py b/rest_framework/settings.py
index 8db9c81eda..d31cf70224 100644
--- a/rest_framework/settings.py
+++ b/rest_framework/settings.py
@@ -18,7 +18,6 @@
 REST framework settings, checking for user settings first, then falling
 back to the defaults.
 """
-from __future__ import unicode_literals
 
 from importlib import import_module
 
@@ -187,7 +186,7 @@ def import_from_string(val, setting_name):
         raise ImportError(msg)
 
 
-class APISettings(object):
+class APISettings:
     """
     A settings object, that allows API settings to be accessed as properties.
     For example:
diff --git a/rest_framework/status.py b/rest_framework/status.py
index 4b4561cfcd..1489b440cf 100644
--- a/rest_framework/status.py
+++ b/rest_framework/status.py
@@ -5,7 +5,6 @@
 And RFC 6585 - https://tools.ietf.org/html/rfc6585
 And RFC 4918 - https://tools.ietf.org/html/rfc4918
 """
-from __future__ import unicode_literals
 
 
 def is_informational(code):
diff --git a/rest_framework/templatetags/rest_framework.py b/rest_framework/templatetags/rest_framework.py
index f48675d5eb..15a37fcdc2 100644
--- a/rest_framework/templatetags/rest_framework.py
+++ b/rest_framework/templatetags/rest_framework.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
 import re
 from collections import OrderedDict
 
diff --git a/rest_framework/test.py b/rest_framework/test.py
index edacf0066d..d7e9ffd1f0 100644
--- a/rest_framework/test.py
+++ b/rest_framework/test.py
@@ -1,8 +1,6 @@
-# -- coding: utf-8 --
-
 # Note that we import as `DjangoRequestFactory` and `DjangoClient` in order
 # to make it harder for the user to import the wrong thing without realizing.
-from __future__ import unicode_literals
+
 
 import io
 from importlib import import_module
@@ -32,7 +30,7 @@ class HeaderDict(requests.packages.urllib3._collections.HTTPHeaderDict):
         def get_all(self, key, default):
             return self.getheaders(key)
 
-    class MockOriginalResponse(object):
+    class MockOriginalResponse:
         def __init__(self, headers):
             self.msg = HeaderDict(headers)
             self.closed = False
diff --git a/rest_framework/throttling.py b/rest_framework/throttling.py
index 834ced148e..6c497edc5b 100644
--- a/rest_framework/throttling.py
+++ b/rest_framework/throttling.py
@@ -1,7 +1,6 @@
 """
 Provides various throttling policies.
 """
-from __future__ import unicode_literals
 
 import time
 
@@ -11,7 +10,7 @@
 from rest_framework.settings import api_settings
 
 
-class BaseThrottle(object):
+class BaseThrottle:
     """
     Rate throttling of requests.
     """
diff --git a/rest_framework/urlpatterns.py b/rest_framework/urlpatterns.py
index ab3a74978f..831d344ddc 100644
--- a/rest_framework/urlpatterns.py
+++ b/rest_framework/urlpatterns.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.conf.urls import include, url
 
 from rest_framework.compat import (
diff --git a/rest_framework/urls.py b/rest_framework/urls.py
index 0e4c2661bd..521a3db759 100644
--- a/rest_framework/urls.py
+++ b/rest_framework/urls.py
@@ -11,7 +11,6 @@
 
 You should make sure your authentication settings include `SessionAuthentication`.
 """
-from __future__ import unicode_literals
 
 from django.conf.urls import url
 from django.contrib.auth import views
diff --git a/rest_framework/utils/breadcrumbs.py b/rest_framework/utils/breadcrumbs.py
index e0374ffd00..54990e9f6c 100644
--- a/rest_framework/utils/breadcrumbs.py
+++ b/rest_framework/utils/breadcrumbs.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.urls import get_script_prefix, resolve
 
 
diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py
index d8f4aeb4eb..9f74409896 100644
--- a/rest_framework/utils/encoders.py
+++ b/rest_framework/utils/encoders.py
@@ -1,8 +1,6 @@
 """
 Helper classes for parsers.
 """
-from __future__ import absolute_import, unicode_literals
-
 import datetime
 import decimal
 import json  # noqa
@@ -65,4 +63,4 @@ def default(self, obj):
                 pass
         elif hasattr(obj, '__iter__'):
             return tuple(item for item in obj)
-        return super(JSONEncoder, self).default(obj)
+        return super().default(obj)
diff --git a/rest_framework/utils/field_mapping.py b/rest_framework/utils/field_mapping.py
index 927d08ff25..1281ee1672 100644
--- a/rest_framework/utils/field_mapping.py
+++ b/rest_framework/utils/field_mapping.py
@@ -16,7 +16,7 @@
 )
 
 
-class ClassLookupDict(object):
+class ClassLookupDict:
     """
     Takes a dictionary with classes as keys.
     Lookups against this object will traverses the object's inheritance
diff --git a/rest_framework/utils/formatting.py b/rest_framework/utils/formatting.py
index aa805f14e3..0c58665a8e 100644
--- a/rest_framework/utils/formatting.py
+++ b/rest_framework/utils/formatting.py
@@ -1,7 +1,6 @@
 """
 Utility functions to return a formatted name and description for a given view.
 """
-from __future__ import unicode_literals
 
 import re
 
diff --git a/rest_framework/utils/json.py b/rest_framework/utils/json.py
index cb55723801..82b306ddab 100644
--- a/rest_framework/utils/json.py
+++ b/rest_framework/utils/json.py
@@ -6,8 +6,6 @@
 handled by users at the renderer and parser layer.
 """
 
-from __future__ import absolute_import
-
 import functools
 import json  # noqa
 
diff --git a/rest_framework/utils/mediatypes.py b/rest_framework/utils/mediatypes.py
index f4acf4807e..e808dfa362 100644
--- a/rest_framework/utils/mediatypes.py
+++ b/rest_framework/utils/mediatypes.py
@@ -3,10 +3,8 @@
 
 See https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
 """
-from __future__ import unicode_literals
 
 from django.http.multipartparser import parse_header
-from django.utils.encoding import python_2_unicode_compatible
 
 from rest_framework import HTTP_HEADER_ENCODING
 
@@ -46,8 +44,7 @@ def order_by_precedence(media_type_lst):
     return [media_types for media_types in ret if media_types]
 
 
-@python_2_unicode_compatible
-class _MediaType(object):
+class _MediaType:
     def __init__(self, media_type_str):
         self.orig = '' if (media_type_str is None) else media_type_str
         self.full_type, self.params = parse_header(self.orig.encode(HTTP_HEADER_ENCODING))
diff --git a/rest_framework/utils/representation.py b/rest_framework/utils/representation.py
index deeaf1f63f..6290065e3c 100644
--- a/rest_framework/utils/representation.py
+++ b/rest_framework/utils/representation.py
@@ -2,7 +2,6 @@
 Helper functions for creating user-friendly representations
 of serializer classes and serializer fields.
 """
-from __future__ import unicode_literals
 
 import re
 
diff --git a/rest_framework/utils/serializer_helpers.py b/rest_framework/utils/serializer_helpers.py
index c24e51d091..8e27a925bb 100644
--- a/rest_framework/utils/serializer_helpers.py
+++ b/rest_framework/utils/serializer_helpers.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from collections import OrderedDict
 
 from django.utils.encoding import force_text
@@ -17,7 +15,7 @@ class ReturnDict(OrderedDict):
 
     def __init__(self, *args, **kwargs):
         self.serializer = kwargs.pop('serializer')
-        super(ReturnDict, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def copy(self):
         return ReturnDict(self, serializer=self.serializer)
@@ -40,7 +38,7 @@ class ReturnList(list):
 
     def __init__(self, *args, **kwargs):
         self.serializer = kwargs.pop('serializer')
-        super(ReturnList, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
     def __repr__(self):
         return list.__repr__(self)
@@ -51,7 +49,7 @@ def __reduce__(self):
         return (list, (list(self),))
 
 
-class BoundField(object):
+class BoundField:
     """
     A field object that also includes `.value` and `.error` properties.
     Returned when iterating over a serializer instance,
@@ -105,7 +103,7 @@ class NestedBoundField(BoundField):
     def __init__(self, field, value, errors, prefix=''):
         if value is None or value is '':
             value = {}
-        super(NestedBoundField, self).__init__(field, value, errors, prefix)
+        super().__init__(field, value, errors, prefix)
 
     def __iter__(self):
         for field in self.fields.values():
diff --git a/rest_framework/validators.py b/rest_framework/validators.py
index 2ea3e5ac15..1976f0bc59 100644
--- a/rest_framework/validators.py
+++ b/rest_framework/validators.py
@@ -6,7 +6,6 @@
 object creation, and makes it possible to switch between using the implicit
 `ModelSerializer` class and an equivalent explicit `Serializer` class.
 """
-from __future__ import unicode_literals
 
 from django.db import DataError
 from django.utils.translation import ugettext_lazy as _
@@ -33,7 +32,7 @@ def qs_filter(queryset, **kwargs):
         return queryset.none()
 
 
-class UniqueValidator(object):
+class UniqueValidator:
     """
     Validator that corresponds to `unique=True` on a model field.
 
@@ -88,7 +87,7 @@ def __repr__(self):
         ))
 
 
-class UniqueTogetherValidator(object):
+class UniqueTogetherValidator:
     """
     Validator that corresponds to `unique_together = (...)` on a model class.
 
@@ -177,7 +176,7 @@ def __repr__(self):
         ))
 
 
-class BaseUniqueForValidator(object):
+class BaseUniqueForValidator:
     message = None
     missing_message = _('This field is required.')
 
diff --git a/rest_framework/versioning.py b/rest_framework/versioning.py
index 206ff6c2ec..d776df8ce9 100644
--- a/rest_framework/versioning.py
+++ b/rest_framework/versioning.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import re
 
 from django.utils.translation import ugettext_lazy as _
@@ -13,7 +10,7 @@
 from rest_framework.utils.mediatypes import _MediaType
 
 
-class BaseVersioning(object):
+class BaseVersioning:
     default_version = api_settings.DEFAULT_VERSION
     allowed_versions = api_settings.ALLOWED_VERSIONS
     version_param = api_settings.VERSION_PARAM
diff --git a/rest_framework/views.py b/rest_framework/views.py
index 9d5d959e9d..98e6517765 100644
--- a/rest_framework/views.py
+++ b/rest_framework/views.py
@@ -1,7 +1,6 @@
 """
 Provides an APIView class that is the base of all views in REST framework.
 """
-from __future__ import unicode_literals
 
 from django.conf import settings
 from django.core.exceptions import PermissionDenied
diff --git a/rest_framework/viewsets.py b/rest_framework/viewsets.py
index 7146828d2f..68d6611391 100644
--- a/rest_framework/viewsets.py
+++ b/rest_framework/viewsets.py
@@ -16,7 +16,6 @@
     router.register(r'users', UserViewSet, 'user')
     urlpatterns = router.urls
 """
-from __future__ import unicode_literals
 
 from collections import OrderedDict
 from functools import update_wrapper
@@ -34,7 +33,7 @@ def _is_extra_action(attr):
     return hasattr(attr, 'mapping')
 
 
-class ViewSetMixin(object):
+class ViewSetMixin:
     """
     This is the magic.
 
diff --git a/tests/authentication/migrations/0001_initial.py b/tests/authentication/migrations/0001_initial.py
index cfc8872400..548b3576bb 100644
--- a/tests/authentication/migrations/0001_initial.py
+++ b/tests/authentication/migrations/0001_initial.py
@@ -1,6 +1,3 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
 from django.conf import settings
 from django.db import migrations, models
 
diff --git a/tests/authentication/models.py b/tests/authentication/models.py
index b8d1fd5a6b..1a721de4d3 100644
--- a/tests/authentication/models.py
+++ b/tests/authentication/models.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 from django.conf import settings
 from django.db import models
 
diff --git a/tests/authentication/test_authentication.py b/tests/authentication/test_authentication.py
index 7937735424..8e7ccb9927 100644
--- a/tests/authentication/test_authentication.py
+++ b/tests/authentication/test_authentication.py
@@ -1,7 +1,3 @@
-# coding: utf-8
-
-from __future__ import unicode_literals
-
 import base64
 
 import pytest
@@ -253,7 +249,7 @@ def test_post_form_session_auth_failing(self):
         assert response.status_code == status.HTTP_403_FORBIDDEN
 
 
-class BaseTokenAuthTests(object):
+class BaseTokenAuthTests:
     """Token authentication"""
     model = None
     path = None
diff --git a/tests/browsable_api/auth_urls.py b/tests/browsable_api/auth_urls.py
index 0e93797172..7530c5e408 100644
--- a/tests/browsable_api/auth_urls.py
+++ b/tests/browsable_api/auth_urls.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.conf.urls import include, url
 
 from .views import MockView
diff --git a/tests/browsable_api/no_auth_urls.py b/tests/browsable_api/no_auth_urls.py
index 5fc95c7276..348bfe1c0c 100644
--- a/tests/browsable_api/no_auth_urls.py
+++ b/tests/browsable_api/no_auth_urls.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.conf.urls import url
 
 from .views import MockView
diff --git a/tests/browsable_api/test_browsable_api.py b/tests/browsable_api/test_browsable_api.py
index 684d7ae143..81090e2235 100644
--- a/tests/browsable_api/test_browsable_api.py
+++ b/tests/browsable_api/test_browsable_api.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.contrib.auth.models import User
 from django.test import TestCase, override_settings
 
diff --git a/tests/browsable_api/test_browsable_nested_api.py b/tests/browsable_api/test_browsable_nested_api.py
index 8f38b3c4e5..3fef74023d 100644
--- a/tests/browsable_api/test_browsable_nested_api.py
+++ b/tests/browsable_api/test_browsable_nested_api.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.conf.urls import url
 from django.test import TestCase
 from django.test.utils import override_settings
diff --git a/tests/browsable_api/test_form_rendering.py b/tests/browsable_api/test_form_rendering.py
index d8378a2cab..ff2d0e05a9 100644
--- a/tests/browsable_api/test_form_rendering.py
+++ b/tests/browsable_api/test_form_rendering.py
@@ -1,9 +1,9 @@
 from django.test import TestCase
+from tests.models import BasicModel
 
 from rest_framework import generics, renderers, serializers, status
 from rest_framework.response import Response
 from rest_framework.test import APIRequestFactory
-from tests.models import BasicModel
 
 factory = APIRequestFactory()
 
diff --git a/tests/browsable_api/views.py b/tests/browsable_api/views.py
index 03758f10b3..e1cf13a1ec 100644
--- a/tests/browsable_api/views.py
+++ b/tests/browsable_api/views.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from rest_framework import authentication, renderers
 from rest_framework.response import Response
 from rest_framework.views import APIView
diff --git a/tests/generic_relations/models.py b/tests/generic_relations/models.py
index 55bc243cbd..d0e2e9b559 100644
--- a/tests/generic_relations/models.py
+++ b/tests/generic_relations/models.py
@@ -5,10 +5,8 @@
 )
 from django.contrib.contenttypes.models import ContentType
 from django.db import models
-from django.utils.encoding import python_2_unicode_compatible
 
 
-@python_2_unicode_compatible
 class Tag(models.Model):
     """
     Tags have a descriptive slug, and are attached to an arbitrary object.
@@ -22,7 +20,6 @@ def __str__(self):
         return self.tag
 
 
-@python_2_unicode_compatible
 class Bookmark(models.Model):
     """
     A URL bookmark that may have multiple tags attached.
@@ -34,7 +31,6 @@ def __str__(self):
         return 'Bookmark: %s' % self.url
 
 
-@python_2_unicode_compatible
 class Note(models.Model):
     """
     A textual note that may have multiple tags attached.
diff --git a/tests/generic_relations/test_generic_relations.py b/tests/generic_relations/test_generic_relations.py
index c8de332e1d..c6f2b0de4d 100644
--- a/tests/generic_relations/test_generic_relations.py
+++ b/tests/generic_relations/test_generic_relations.py
@@ -1,10 +1,46 @@
-from __future__ import unicode_literals
-
+from django.contrib.contenttypes.fields import (
+    GenericForeignKey, GenericRelation
+)
+from django.contrib.contenttypes.models import ContentType
+from django.db import models
 from django.test import TestCase
 
 from rest_framework import serializers
 
-from .models import Bookmark, Note, Tag
+
+class Tag(models.Model):
+    """
+    Tags have a descriptive slug, and are attached to an arbitrary object.
+    """
+    tag = models.SlugField()
+    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
+    object_id = models.PositiveIntegerField()
+    tagged_item = GenericForeignKey('content_type', 'object_id')
+
+    def __str__(self):
+        return self.tag
+
+
+class Bookmark(models.Model):
+    """
+    A URL bookmark that may have multiple tags attached.
+    """
+    url = models.URLField()
+    tags = GenericRelation(Tag)
+
+    def __str__(self):
+        return 'Bookmark: %s' % self.url
+
+
+class Note(models.Model):
+    """
+    A textual note that may have multiple tags attached.
+    """
+    text = models.TextField()
+    tags = GenericRelation(Tag)
+
+    def __str__(self):
+        return 'Note: %s' % self.text
 
 
 class TestGenericRelations(TestCase):
diff --git a/tests/importable/test_installed.py b/tests/importable/test_installed.py
index 072d3b2e43..fff51fd8f9 100644
--- a/tests/importable/test_installed.py
+++ b/tests/importable/test_installed.py
@@ -1,5 +1,4 @@
 from django.conf import settings
-
 from tests import importable
 
 
diff --git a/tests/models.py b/tests/models.py
index 17bf23cda4..f389a51a92 100644
--- a/tests/models.py
+++ b/tests/models.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import uuid
 
 from django.db import models
diff --git a/tests/test_api_client.py b/tests/test_api_client.py
index e4354ec603..74a3579e2f 100644
--- a/tests/test_api_client.py
+++ b/tests/test_api_client.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import os
 import tempfile
 import unittest
diff --git a/tests/test_atomic_requests.py b/tests/test_atomic_requests.py
index bddd480a5a..aba54bf70a 100644
--- a/tests/test_atomic_requests.py
+++ b/tests/test_atomic_requests.py
@@ -1,18 +1,16 @@
-from __future__ import unicode_literals
-
 import unittest
 
 from django.conf.urls import url
 from django.db import connection, connections, transaction
 from django.http import Http404
 from django.test import TestCase, TransactionTestCase, override_settings
+from tests.models import BasicModel
 
 from rest_framework import status
 from rest_framework.exceptions import APIException
 from rest_framework.response import Response
 from rest_framework.test import APIRequestFactory
 from rest_framework.views import APIView
-from tests.models import BasicModel
 
 factory = APIRequestFactory()
 
diff --git a/tests/test_decorators.py b/tests/test_decorators.py
index 13dd41ff3a..3f24e7ef03 100644
--- a/tests/test_decorators.py
+++ b/tests/test_decorators.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import pytest
 from django.test import TestCase
 
diff --git a/tests/test_description.py b/tests/test_description.py
index 702e56332f..ae00fe4a97 100644
--- a/tests/test_description.py
+++ b/tests/test_description.py
@@ -1,9 +1,4 @@
-# -- coding: utf-8 --
-
-from __future__ import unicode_literals
-
 from django.test import TestCase
-from django.utils.encoding import python_2_unicode_compatible
 
 from rest_framework.compat import apply_markdown
 from rest_framework.utils.formatting import dedent
@@ -157,8 +152,8 @@ class that can be converted to a string.
         """
         # use a mock object instead of gettext_lazy to ensure that we can't end
         # up with a test case string in our l10n catalog
-        @python_2_unicode_compatible
-        class MockLazyStr(object):
+
+        class MockLazyStr:
             def __init__(self, string):
                 self.s = string
 
diff --git a/tests/test_encoders.py b/tests/test_encoders.py
index 12eca8105d..c66954b807 100644
--- a/tests/test_encoders.py
+++ b/tests/test_encoders.py
@@ -10,7 +10,7 @@
 from rest_framework.utils.encoders import JSONEncoder
 
 
-class MockList(object):
+class MockList:
     def tolist(self):
         return [1, 2, 3]
 
diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py
index ce0ed8514f..a21334d84e 100644
--- a/tests/test_exceptions.py
+++ b/tests/test_exceptions.py
@@ -1,6 +1,3 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
 from django.test import RequestFactory, TestCase
 from django.utils import six, translation
 from django.utils.translation import ugettext_lazy as _
diff --git a/tests/test_fields.py b/tests/test_fields.py
index 12c936b229..1e04883deb 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -192,7 +192,7 @@ def test_callable_source(self):
         class ExampleSerializer(serializers.Serializer):
             example_field = serializers.CharField(source='example_callable')
 
-        class ExampleInstance(object):
+        class ExampleInstance:
             def example_callable(self):
                 return 'example callable value'
 
@@ -203,7 +203,7 @@ def test_callable_source_raises(self):
         class ExampleSerializer(serializers.Serializer):
             example_field = serializers.CharField(source='example_callable', read_only=True)
 
-        class ExampleInstance(object):
+        class ExampleInstance:
             def example_callable(self):
                 raise AttributeError('method call failed')
 
diff --git a/tests/test_filters.py b/tests/test_filters.py
index 088d25436d..0f619a310d 100644
--- a/tests/test_filters.py
+++ b/tests/test_filters.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import datetime
 
 import pytest
diff --git a/tests/test_generateschema.py b/tests/test_generateschema.py
index 915c6ea059..d09b668ec9 100644
--- a/tests/test_generateschema.py
+++ b/tests/test_generateschema.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import pytest
 from django.conf.urls import url
 from django.core.management import call_command
diff --git a/tests/test_generics.py b/tests/test_generics.py
index c0ff1c5c4e..74e760307a 100644
--- a/tests/test_generics.py
+++ b/tests/test_generics.py
@@ -1,20 +1,18 @@
-from __future__ import unicode_literals
-
 import pytest
 from django.db import models
 from django.http import Http404
 from django.shortcuts import get_object_or_404
 from django.test import TestCase
 from django.utils import six
-
-from rest_framework import generics, renderers, serializers, status
-from rest_framework.response import Response
-from rest_framework.test import APIRequestFactory
 from tests.models import (
     BasicModel, ForeignKeySource, ForeignKeyTarget, RESTFrameworkModel,
     UUIDForeignKeyTarget
 )
 
+from rest_framework import generics, renderers, serializers, status
+from rest_framework.response import Response
+from rest_framework.test import APIRequestFactory
+
 factory = APIRequestFactory()
 
 
diff --git a/tests/test_htmlrenderer.py b/tests/test_htmlrenderer.py
index decd25a3fe..9ae3d0b8f8 100644
--- a/tests/test_htmlrenderer.py
+++ b/tests/test_htmlrenderer.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import django.template.loader
 import pytest
 from django.conf.urls import url
@@ -47,7 +45,7 @@ def not_found(request):
 @override_settings(ROOT_URLCONF='tests.test_htmlrenderer')
 class TemplateHTMLRendererTests(TestCase):
     def setUp(self):
-        class MockResponse(object):
+        class MockResponse:
             template_name = None
         self.mock_response = MockResponse()
         self._monkey_patch_get_template()
@@ -105,14 +103,14 @@ def test_get_template_names_returns_own_template_name(self):
     def test_get_template_names_returns_view_template_name(self):
         renderer = TemplateHTMLRenderer()
 
-        class MockResponse(object):
+        class MockResponse:
             template_name = None
 
-        class MockView(object):
+        class MockView:
             def get_template_names(self):
                 return ['template from get_template_names method']
 
-        class MockView2(object):
+        class MockView2:
             template_name = 'template from template_name attribute'
 
         template_name = renderer.get_template_names(self.mock_response,
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
index fe4ea4b428..e1a1fd3528 100644
--- a/tests/test_metadata.py
+++ b/tests/test_metadata.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import pytest
 from django.core.validators import MaxValueValidator, MinValueValidator
 from django.db import models
diff --git a/tests/test_middleware.py b/tests/test_middleware.py
index 9df7d8e3e6..28a5e558a1 100644
--- a/tests/test_middleware.py
+++ b/tests/test_middleware.py
@@ -22,7 +22,7 @@ def post(self, request):
 ]
 
 
-class RequestUserMiddleware(object):
+class RequestUserMiddleware:
     def __init__(self, get_response):
         self.get_response = get_response
 
@@ -34,7 +34,7 @@ def __call__(self, request):
         return response
 
 
-class RequestPOSTMiddleware(object):
+class RequestPOSTMiddleware:
     def __init__(self, get_response):
         self.get_response = get_response
 
diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py
index 898c859a4f..a89f916af7 100644
--- a/tests/test_model_serializer.py
+++ b/tests/test_model_serializer.py
@@ -5,8 +5,6 @@
 These tests deal with ensuring that we correctly map the model fields onto
 an appropriate set of serializer fields for each case.
 """
-from __future__ import unicode_literals
-
 import datetime
 import decimal
 import sys
diff --git a/tests/test_multitable_inheritance.py b/tests/test_multitable_inheritance.py
index 2ddd37ebba..772bc69d63 100644
--- a/tests/test_multitable_inheritance.py
+++ b/tests/test_multitable_inheritance.py
@@ -1,10 +1,8 @@
-from __future__ import unicode_literals
-
 from django.db import models
 from django.test import TestCase
+from tests.models import RESTFrameworkModel
 
 from rest_framework import serializers
-from tests.models import RESTFrameworkModel
 
 
 # Models
diff --git a/tests/test_negotiation.py b/tests/test_negotiation.py
index 7ce3f92a9b..089a86c624 100644
--- a/tests/test_negotiation.py
+++ b/tests/test_negotiation.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import pytest
 from django.http import Http404
 from django.test import TestCase
@@ -80,7 +78,7 @@ def test_mediatype_string_representation(self):
         assert str(mediatype) == 'test/*; foo=bar'
 
     def test_raise_error_if_no_suitable_renderers_found(self):
-        class MockRenderer(object):
+        class MockRenderer:
             format = 'xml'
         renderers = [MockRenderer()]
         with pytest.raises(Http404):
diff --git a/tests/test_one_to_one_with_inheritance.py b/tests/test_one_to_one_with_inheritance.py
index 789c7fcb97..35758544c1 100644
--- a/tests/test_one_to_one_with_inheritance.py
+++ b/tests/test_one_to_one_with_inheritance.py
@@ -1,13 +1,11 @@
-from __future__ import unicode_literals
-
 from django.db import models
 from django.test import TestCase
-
-from rest_framework import serializers
 from tests.models import RESTFrameworkModel
 # Models
 from tests.test_multitable_inheritance import ChildModel
 
+from rest_framework import serializers
+
 
 # Regression test for #4290
 class ChildAssociatedModel(RESTFrameworkModel):
diff --git a/tests/test_pagination.py b/tests/test_pagination.py
index 6d940fe2b0..26510fe984 100644
--- a/tests/test_pagination.py
+++ b/tests/test_pagination.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import pytest
 from django.core.paginator import Paginator as DjangoPaginator
 from django.db import models
@@ -799,11 +796,11 @@ class TestCursorPagination(CursorPaginationTestsMixin):
     """
 
     def setup(self):
-        class MockObject(object):
+        class MockObject:
             def __init__(self, idx):
                 self.created = idx
 
-        class MockQuerySet(object):
+        class MockQuerySet:
             def __init__(self, items):
                 self.items = items
 
diff --git a/tests/test_parsers.py b/tests/test_parsers.py
index e793948e37..e77950be93 100644
--- a/tests/test_parsers.py
+++ b/tests/test_parsers.py
@@ -1,6 +1,3 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
 import io
 import math
 
@@ -42,7 +39,7 @@ def test_parse(self):
 
 class TestFileUploadParser(TestCase):
     def setUp(self):
-        class MockRequest(object):
+        class MockRequest:
             pass
         self.stream = io.BytesIO(
             "Test text file".encode('utf-8')
diff --git a/tests/test_permissions.py b/tests/test_permissions.py
index 2fabdfa05c..04fb3700f8 100644
--- a/tests/test_permissions.py
+++ b/tests/test_permissions.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import base64
 import unittest
 import warnings
@@ -19,6 +17,7 @@
 from rest_framework.filters import DjangoObjectPermissionsFilter
 from rest_framework.routers import DefaultRouter
 from rest_framework.test import APIRequestFactory
+
 from tests.models import BasicModel
 
 factory = APIRequestFactory()
diff --git a/tests/test_relations_hyperlink.py b/tests/test_relations_hyperlink.py
index 887a6f423a..2cc0e45e28 100644
--- a/tests/test_relations_hyperlink.py
+++ b/tests/test_relations_hyperlink.py
@@ -1,15 +1,13 @@
-from __future__ import unicode_literals
-
 from django.conf.urls import url
 from django.test import TestCase, override_settings
-
-from rest_framework import serializers
-from rest_framework.test import APIRequestFactory
 from tests.models import (
     ForeignKeySource, ForeignKeyTarget, ManyToManySource, ManyToManyTarget,
     NullableForeignKeySource, NullableOneToOneSource, OneToOneTarget
 )
 
+from rest_framework import serializers
+from rest_framework.test import APIRequestFactory
+
 factory = APIRequestFactory()
 request = factory.get('/')  # Just to ensure we have a request in the serializer context
 
diff --git a/tests/test_relations_pk.py b/tests/test_relations_pk.py
index 2cffb62e6b..c5e5629b7a 100644
--- a/tests/test_relations_pk.py
+++ b/tests/test_relations_pk.py
@@ -1,9 +1,5 @@
-from __future__ import unicode_literals
-
 from django.test import TestCase
 from django.utils import six
-
-from rest_framework import serializers
 from tests.models import (
     ForeignKeySource, ForeignKeySourceWithLimitedChoices,
     ForeignKeySourceWithQLimitedChoices, ForeignKeyTarget, ManyToManySource,
@@ -12,6 +8,8 @@
     UUIDForeignKeyTarget
 )
 
+from rest_framework import serializers
+
 
 # ManyToMany
 class ManyToManyTargetSerializer(serializers.ModelSerializer):
diff --git a/tests/test_relations_slug.py b/tests/test_relations_slug.py
index 0b9ca79d3d..d79eb86278 100644
--- a/tests/test_relations_slug.py
+++ b/tests/test_relations_slug.py
@@ -1,10 +1,10 @@
 from django.test import TestCase
-
-from rest_framework import serializers
 from tests.models import (
     ForeignKeySource, ForeignKeyTarget, NullableForeignKeySource
 )
 
+from rest_framework import serializers
+
 
 class ForeignKeyTargetSerializer(serializers.ModelSerializer):
     sources = serializers.SlugRelatedField(
diff --git a/tests/test_renderers.py b/tests/test_renderers.py
index 60a0c0307d..17afa09fbe 100644
--- a/tests/test_renderers.py
+++ b/tests/test_renderers.py
@@ -1,6 +1,3 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
 import re
 from collections import OrderedDict
 
@@ -348,7 +345,7 @@ def keys(self):
         self.assertEqual(data, {'key': 'string value', '2': 3})
 
     def test_render_obj_with_getitem(self):
-        class DictLike(object):
+        class DictLike:
             def __init__(self):
                 self._dict = {}
 
@@ -647,7 +644,7 @@ def test_get_description_returns_empty_string_for_401_and_403_statuses(self):
         assert self.renderer.get_description({}, status_code=403) == ''
 
     def test_get_filter_form_returns_none_if_data_is_not_list_instance(self):
-        class DummyView(object):
+        class DummyView:
             get_queryset = None
             filter_backends = None
 
diff --git a/tests/test_request.py b/tests/test_request.py
index 83d295a128..488193cc0e 100644
--- a/tests/test_request.py
+++ b/tests/test_request.py
@@ -1,8 +1,6 @@
 """
 Tests for content parsing, and form-overloaded content parsing.
 """
-from __future__ import unicode_literals
-
 import os.path
 import tempfile
 
diff --git a/tests/test_requests_client.py b/tests/test_requests_client.py
index 161429f73e..59b388c5a6 100644
--- a/tests/test_requests_client.py
+++ b/tests/test_requests_client.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import unittest
 
 from django.conf.urls import url
diff --git a/tests/test_response.py b/tests/test_response.py
index e92bf54c16..66fce9aec8 100644
--- a/tests/test_response.py
+++ b/tests/test_response.py
@@ -1,8 +1,7 @@
-from __future__ import unicode_literals
-
 from django.conf.urls import include, url
 from django.test import TestCase, override_settings
 from django.utils import six
+from tests.models import BasicModel
 
 from rest_framework import generics, routers, serializers, status, viewsets
 from rest_framework.parsers import JSONParser
@@ -11,7 +10,6 @@
 )
 from rest_framework.response import Response
 from rest_framework.views import APIView
-from tests.models import BasicModel
 
 
 # Serializer used to test BasicModel
diff --git a/tests/test_reverse.py b/tests/test_reverse.py
index 145b1a54f3..9ab1667c52 100644
--- a/tests/test_reverse.py
+++ b/tests/test_reverse.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.conf.urls import url
 from django.test import TestCase, override_settings
 from django.urls import NoReverseMatch
@@ -19,7 +17,7 @@ def null_view(request):
 ]
 
 
-class MockVersioningScheme(object):
+class MockVersioningScheme:
 
     def __init__(self, raise_error=False):
         self.raise_error = raise_error
diff --git a/tests/test_routers.py b/tests/test_routers.py
index cca2ea7122..adcec8bd62 100644
--- a/tests/test_routers.py
+++ b/tests/test_routers.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import warnings
 from collections import namedtuple
 
diff --git a/tests/test_schemas.py b/tests/test_schemas.py
index 3cb9e0cda8..fc7a8302d0 100644
--- a/tests/test_schemas.py
+++ b/tests/test_schemas.py
@@ -29,7 +29,7 @@
 factory = APIRequestFactory()
 
 
-class MockUser(object):
+class MockUser:
     def is_authenticated(self):
         return True
 
diff --git a/tests/test_serializer.py b/tests/test_serializer.py
index 0f1e81965a..8a1df04ec0 100644
--- a/tests/test_serializer.py
+++ b/tests/test_serializer.py
@@ -1,6 +1,3 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
 import inspect
 import pickle
 import re
@@ -160,7 +157,7 @@ def test_custom_to_internal_value(self):
         to_internal_value() is expected to return a dict, but subclasses may
         return application specific type.
         """
-        class Point(object):
+        class Point:
             def __init__(self, srid, x, y):
                 self.srid = srid
                 self.coords = (x, y)
diff --git a/tests/test_serializer_bulk_update.py b/tests/test_serializer_bulk_update.py
index d9e5d79782..82c14bf81e 100644
--- a/tests/test_serializer_bulk_update.py
+++ b/tests/test_serializer_bulk_update.py
@@ -1,8 +1,6 @@
 """
 Tests to cover bulk create and update using serializers.
 """
-from __future__ import unicode_literals
-
 from django.test import TestCase
 from django.utils import six
 
diff --git a/tests/test_settings.py b/tests/test_settings.py
index 51e9751b25..b78125ff95 100644
--- a/tests/test_settings.py
+++ b/tests/test_settings.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.test import TestCase, override_settings
 
 from rest_framework.settings import APISettings, api_settings
diff --git a/tests/test_status.py b/tests/test_status.py
index 1cd6e229e9..07d893bee9 100644
--- a/tests/test_status.py
+++ b/tests/test_status.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.test import TestCase
 
 from rest_framework.status import (
diff --git a/tests/test_templatetags.py b/tests/test_templatetags.py
index 45bfd4aeb7..796a7f6775 100644
--- a/tests/test_templatetags.py
+++ b/tests/test_templatetags.py
@@ -1,6 +1,3 @@
-# encoding: utf-8
-from __future__ import unicode_literals
-
 import unittest
 
 from django.template import Context, Template
diff --git a/tests/test_testing.py b/tests/test_testing.py
index 7868f724c1..b7fc7e3081 100644
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -1,6 +1,3 @@
-# encoding: utf-8
-from __future__ import unicode_literals
-
 from io import BytesIO
 
 from django.conf.urls import url
diff --git a/tests/test_throttling.py b/tests/test_throttling.py
index b220a33a6f..b20b6a809c 100644
--- a/tests/test_throttling.py
+++ b/tests/test_throttling.py
@@ -1,7 +1,6 @@
 """
 Tests for the throttling implementations in the permissions module.
 """
-from __future__ import unicode_literals
 
 import pytest
 from django.contrib.auth.models import User
@@ -296,7 +295,7 @@ def test_unscoped_view_not_throttled(self):
             assert response.status_code == 200
 
     def test_get_cache_key_returns_correct_key_if_user_is_authenticated(self):
-        class DummyView(object):
+        class DummyView:
             throttle_scope = 'user'
 
         request = Request(HttpRequest())
diff --git a/tests/test_urlpatterns.py b/tests/test_urlpatterns.py
index 59ba395d29..25cc0032ee 100644
--- a/tests/test_urlpatterns.py
+++ b/tests/test_urlpatterns.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import unittest
 from collections import namedtuple
 
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 28b06b1735..996b3c8afc 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,6 +1,3 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
 from django.conf.urls import url
 from django.test import TestCase, override_settings
 
@@ -12,6 +9,7 @@
 from rest_framework.utils.urls import remove_query_param, replace_query_param
 from rest_framework.views import APIView
 from rest_framework.viewsets import ModelViewSet
+
 from tests.models import BasicModel
 
 
diff --git a/tests/test_validation.py b/tests/test_validation.py
index 4132a7b00f..b2d611e53f 100644
--- a/tests/test_validation.py
+++ b/tests/test_validation.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import re
 
 from django.core.validators import MaxValueValidator, RegexValidator
diff --git a/tests/test_versioning.py b/tests/test_versioning.py
index 7e650e2752..526df8292c 100644
--- a/tests/test_versioning.py
+++ b/tests/test_versioning.py
@@ -321,7 +321,7 @@ class TestHyperlinkedRelatedField(URLPatternsTestCase, APITestCase):
     def setUp(self):
         super(TestHyperlinkedRelatedField, self).setUp()
 
-        class MockQueryset(object):
+        class MockQueryset:
             def get(self, pk):
                 return 'object %s' % pk
 
diff --git a/tests/test_views.py b/tests/test_views.py
index f0919e8461..cca78e8433 100644
--- a/tests/test_views.py
+++ b/tests/test_views.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 import copy
 import sys
 
diff --git a/tests/utils.py b/tests/utils.py
index 509e6a1027..06e5b9abe6 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -2,7 +2,7 @@
 from django.urls import NoReverseMatch
 
 
-class MockObject(object):
+class MockObject:
     def __init__(self, **kwargs):
         self._kwargs = kwargs
         for key, val in kwargs.items():
@@ -16,7 +16,7 @@ def __str__(self):
         return '<MockObject %s>' % kwargs_str
 
 
-class MockQueryset(object):
+class MockQueryset:
     def __init__(self, iterable):
         self.items = iterable
 
@@ -33,7 +33,7 @@ def get(self, **lookup):
         raise ObjectDoesNotExist()
 
 
-class BadType(object):
+class BadType:
     """
     When used as a lookup with a `MockQueryset`, these objects
     will raise a `TypeError`, as occurs in Django when making
diff --git a/tox.ini b/tox.ini
index 776af3b6e7..d478be846d 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,6 @@
 [tox]
 envlist =
-       {py27,py34,py35,py36}-django111,
+       {py34,py35,py36}-django111,
        {py34,py35,py36,py37}-django20,
        {py35,py36,py37}-django21
        {py35,py36,py37}-django22
@@ -44,14 +44,14 @@ deps =
         -rrequirements/requirements-optionals.txt
 
 [testenv:lint]
-basepython = python2.7
+basepython = python3.6
 commands = ./runtests.py --lintonly
 deps =
         -rrequirements/requirements-codestyle.txt
         -rrequirements/requirements-testing.txt
 
 [testenv:docs]
-basepython = python2.7
+basepython = python3.6
 commands = mkdocs build
 deps =
        -rrequirements/requirements-testing.txt