Refs #21127 -- Required on_delete for ForeignKey/OneToOneField.

Per deprecation timeline.
This commit is contained in:
Tim Graham 2016-12-30 17:50:05 -05:00
parent 625e9da9ca
commit ddd3268975
4 changed files with 5 additions and 143 deletions

View File

@ -20,7 +20,6 @@ from django.utils.encoding import force_text
from django.utils.functional import cached_property, curry from django.utils.functional import cached_property, curry
from django.utils.lru_cache import lru_cache from django.utils.lru_cache import lru_cache
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.version import get_docs_version
from . import Field from . import Field
from .related_descriptors import ( from .related_descriptors import (
@ -789,7 +788,7 @@ class ForeignKey(ForeignObject):
} }
description = _("Foreign Key (type determined by related field)") description = _("Foreign Key (type determined by related field)")
def __init__(self, to, on_delete=None, related_name=None, related_query_name=None, def __init__(self, to, on_delete, related_name=None, related_query_name=None,
limit_choices_to=None, parent_link=False, to_field=None, limit_choices_to=None, parent_link=False, to_field=None,
db_constraint=True, **kwargs): db_constraint=True, **kwargs):
try: try:
@ -808,29 +807,6 @@ class ForeignKey(ForeignObject):
# be correct until contribute_to_class is called. Refs #12190. # be correct until contribute_to_class is called. Refs #12190.
to_field = to_field or (to._meta.pk and to._meta.pk.name) to_field = to_field or (to._meta.pk and to._meta.pk.name)
if on_delete is None:
warnings.warn(
"on_delete will be a required arg for %s in Django 2.0. Set "
"it to models.CASCADE on models and in existing migrations "
"if you want to maintain the current default behavior. "
"See https://docs.djangoproject.com/en/%s/ref/models/fields/"
"#django.db.models.ForeignKey.on_delete" % (
self.__class__.__name__,
get_docs_version(),
),
RemovedInDjango20Warning, 2)
on_delete = CASCADE
elif not callable(on_delete):
warnings.warn(
"The signature for {0} will change in Django 2.0. "
"Pass to_field='{1}' as a kwarg instead of as an arg.".format(
self.__class__.__name__,
on_delete,
),
RemovedInDjango20Warning, 2)
on_delete, to_field = to_field, on_delete
kwargs['rel'] = self.rel_class( kwargs['rel'] = self.rel_class(
self, to, to_field, self, to, to_field,
related_name=related_name, related_name=related_name,
@ -1028,33 +1004,8 @@ class OneToOneField(ForeignKey):
description = _("One-to-one relationship") description = _("One-to-one relationship")
def __init__(self, to, on_delete=None, to_field=None, **kwargs): def __init__(self, to, on_delete, to_field=None, **kwargs):
kwargs['unique'] = True kwargs['unique'] = True
if on_delete is None:
warnings.warn(
"on_delete will be a required arg for %s in Django 2.0. Set "
"it to models.CASCADE on models and in existing migrations "
"if you want to maintain the current default behavior. "
"See https://docs.djangoproject.com/en/%s/ref/models/fields/"
"#django.db.models.ForeignKey.on_delete" % (
self.__class__.__name__,
get_docs_version(),
),
RemovedInDjango20Warning, 2)
on_delete = CASCADE
elif not callable(on_delete):
warnings.warn(
"The signature for {0} will change in Django 2.0. "
"Pass to_field='{1}' as a kwarg instead of as an arg.".format(
self.__class__.__name__,
on_delete,
),
RemovedInDjango20Warning, 2)
to_field = on_delete
on_delete = CASCADE # Avoid warning in superclass
super(OneToOneField, self).__init__(to, on_delete, to_field=to_field, **kwargs) super(OneToOneField, self).__init__(to, on_delete, to_field=to_field, **kwargs)
def deconstruct(self): def deconstruct(self):

View File

@ -1277,11 +1277,6 @@ relation works.
null=True, null=True,
) )
.. deprecated:: 1.9
:attr:`~ForeignKey.on_delete` will become a required argument in Django
2.0. In older versions it defaults to ``CASCADE``.
The possible values for :attr:`~ForeignKey.on_delete` are found in The possible values for :attr:`~ForeignKey.on_delete` are found in
:mod:`django.db.models`: :mod:`django.db.models`:

View File

@ -249,3 +249,6 @@ these features.
relative ones when the path is identical is also removed. relative ones when the path is identical is also removed.
* ``Field.rel`` and ``Field.remote_field.to`` are removed. * ``Field.rel`` and ``Field.remote_field.to`` are removed.
* The ``on_delete`` argument for ``ForeignKey`` and ``OneToOneField`` are now
required.

View File

@ -1,17 +1,12 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import warnings
from django.core.checks import Error, Warning as DjangoWarning from django.core.checks import Error, Warning as DjangoWarning
from django.db import models from django.db import models
from django.db.models.fields.related import ForeignObject from django.db.models.fields.related import ForeignObject
from django.test import ignore_warnings
from django.test.testcases import SimpleTestCase, skipIfDBFeature from django.test.testcases import SimpleTestCase, skipIfDBFeature
from django.test.utils import isolate_apps, override_settings from django.test.utils import isolate_apps, override_settings
from django.utils import six from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.version import get_docs_version
@isolate_apps('invalid_models_tests') @isolate_apps('invalid_models_tests')
@ -29,88 +24,6 @@ class RelativeFieldTests(SimpleTestCase):
errors = field.check() errors = field.check()
self.assertEqual(errors, []) self.assertEqual(errors, [])
@ignore_warnings(category=RemovedInDjango20Warning)
def test_valid_foreign_key_without_on_delete(self):
class Target(models.Model):
model = models.IntegerField()
class Model(models.Model):
field = models.ForeignKey(Target, related_name='+')
def test_foreign_key_without_on_delete_warning(self):
with warnings.catch_warnings(record=True) as warns:
warnings.simplefilter('always') # prevent warnings from appearing as errors
class Target(models.Model):
model = models.IntegerField()
class Model(models.Model):
field = models.ForeignKey(Target, related_name='+')
self.assertEqual(len(warns), 1)
self.assertEqual(
str(warns[0].message),
'on_delete will be a required arg for ForeignKey in Django '
'2.0. Set it to models.CASCADE on models and in existing '
'migrations if you want to maintain the current default '
'behavior. See https://docs.djangoproject.com/en/%s/ref/models/fields/'
'#django.db.models.ForeignKey.on_delete' % get_docs_version(),
)
def test_foreign_key_to_field_as_arg(self):
with warnings.catch_warnings(record=True) as warns:
warnings.simplefilter('always') # prevent warnings from appearing as errors
class Target(models.Model):
model = models.IntegerField()
class Model(models.Model):
field = models.ForeignKey(Target, 'id')
self.assertEqual(len(warns), 1)
self.assertEqual(
str(warns[0].message),
"The signature for ForeignKey will change in Django 2.0. "
"Pass to_field='id' as a kwarg instead of as an arg."
)
def test_one_to_one_field_without_on_delete_warning(self):
with warnings.catch_warnings(record=True) as warns:
warnings.simplefilter('always') # prevent warnings from appearing as errors
class Target(models.Model):
model = models.IntegerField()
class Model(models.Model):
field = models.OneToOneField(Target, related_name='+')
self.assertEqual(len(warns), 1)
self.assertEqual(
str(warns[0].message),
'on_delete will be a required arg for OneToOneField in Django '
'2.0. Set it to models.CASCADE on models and in existing '
'migrations if you want to maintain the current default '
'behavior. See https://docs.djangoproject.com/en/%s/ref/models/fields/'
'#django.db.models.ForeignKey.on_delete' % get_docs_version(),
)
def test_one_to_one_field_to_field_as_arg(self):
with warnings.catch_warnings(record=True) as warns:
warnings.simplefilter('always') # prevent warnings from appearing as errors
class Target(models.Model):
model = models.IntegerField()
class Model(models.Model):
field = models.OneToOneField(Target, 'id')
self.assertEqual(len(warns), 1)
self.assertEqual(
str(warns[0].message),
"The signature for OneToOneField will change in Django 2.0. "
"Pass to_field='id' as a kwarg instead of as an arg."
)
def test_foreign_key_to_missing_model(self): def test_foreign_key_to_missing_model(self):
# Model names are resolved when a model is being created, so we cannot # Model names are resolved when a model is being created, so we cannot
# test relative fields in isolation and we need to attach them to a # test relative fields in isolation and we need to attach them to a