Refs #21127 -- Required on_delete for ForeignKey/OneToOneField.
Per deprecation timeline.
This commit is contained in:
parent
625e9da9ca
commit
ddd3268975
|
@ -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):
|
||||||
|
|
|
@ -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`:
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue