From 6252fd6314f66d2d303cc47c791ffefd27169b42 Mon Sep 17 00:00:00 2001 From: Adam Chainz Date: Wed, 23 Nov 2016 22:04:10 +0000 Subject: [PATCH] Fixed #27532 -- Deprecated Model._meta.has_auto_field --- django/contrib/admin/helpers.py | 4 ++-- django/db/models/base.py | 2 +- django/db/models/fields/__init__.py | 4 +--- django/db/models/options.py | 17 +++++++++++++++-- docs/internals/deprecation.txt | 2 ++ docs/releases/1.11.txt | 3 +++ tests/model_meta/test_removedindjango21.py | 22 ++++++++++++++++++++++ 7 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 tests/model_meta/test_removedindjango21.py diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py index 7339d6a0ef..cbe03031a9 100644 --- a/django/contrib/admin/helpers.py +++ b/django/contrib/admin/helpers.py @@ -350,12 +350,12 @@ class InlineAdminForm(AdminForm): def needs_explicit_pk_field(self): # Auto fields are editable (oddly), so need to check for auto or non-editable pk - if self.form._meta.model._meta.has_auto_field or not self.form._meta.model._meta.pk.editable: + if self.form._meta.model._meta.auto_field or not self.form._meta.model._meta.pk.editable: return True # Also search any parents for an auto field. (The pk info is propagated to child # models so that does not need to be checked in parents.) for parent in self.form._meta.model._meta.get_parent_list(): - if parent._meta.has_auto_field: + if parent._meta.auto_field: return True return False diff --git a/django/db/models/base.py b/django/db/models/base.py index 7c339dda5a..e20979770c 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -900,7 +900,7 @@ class Model(six.with_metaclass(ModelBase)): if not pk_set: fields = [f for f in fields if f is not meta.auto_field] - update_pk = bool(meta.has_auto_field and not pk_set) + update_pk = meta.auto_field and not pk_set result = self._do_insert(cls._base_manager, using, fields, update_pk, raw) if update_pk: setattr(self, meta.pk.attname, result) diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 40f1411c58..340e6a41b7 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -948,10 +948,8 @@ class AutoField(Field): return int(value) def contribute_to_class(self, cls, name, **kwargs): - assert not cls._meta.has_auto_field, \ - "A model can't have more than one AutoField." + assert not cls._meta.auto_field, "A model can't have more than one AutoField." super(AutoField, self).contribute_to_class(cls, name, **kwargs) - cls._meta.has_auto_field = True cls._meta.auto_field = self def formfield(self, **kwargs): diff --git a/django/db/models/options.py b/django/db/models/options.py index 04696a4e9e..d19a5a02f1 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -17,7 +17,8 @@ from django.db.models.fields.related import OneToOneField from django.utils import six from django.utils.datastructures import ImmutableList, OrderedSet from django.utils.deprecation import ( - RemovedInDjango20Warning, warn_about_renamed_method, + RemovedInDjango20Warning, RemovedInDjango21Warning, + warn_about_renamed_method, ) from django.utils.encoding import force_text, python_2_unicode_compatible from django.utils.functional import cached_property @@ -113,7 +114,6 @@ class Options(object): self.required_db_vendor = None self.meta = meta self.pk = None - self.has_auto_field = False self.auto_field = None self.abstract = False self.managed = True @@ -825,3 +825,16 @@ class Options(object): # Store result into cache for later access self._get_fields_cache[cache_key] = fields return fields + + @property + def has_auto_field(self): + warnings.warn( + 'Model._meta.has_auto_field is deprecated in favor of checking if ' + 'Model._meta.auto_field is not None.', + RemovedInDjango21Warning, stacklevel=2 + ) + return self.auto_field is not None + + @has_auto_field.setter + def has_auto_field(self, value): + pass diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 53d3ef4e9c..29f4479c5a 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -46,6 +46,8 @@ details on these changes. * The ``USE_ETAGS`` setting will be removed. ``CommonMiddleware`` and ``django.utils.cache.patch_response_headers()`` will no longer set ETags. +* The ``Model._meta.has_auto_field`` attribute will be removed. + .. _deprecation-removed-in-2.0: 2.0 diff --git a/docs/releases/1.11.txt b/docs/releases/1.11.txt index c8c64ab9c9..1b301078f1 100644 --- a/docs/releases/1.11.txt +++ b/docs/releases/1.11.txt @@ -707,3 +707,6 @@ Miscellaneous ``ETag`` header to responses regardless of the setting. ``CommonMiddleware`` and ``django.utils.cache.patch_response_headers()`` will no longer set ETags when the deprecation ends. + +* ``Model._meta.has_auto_field`` is deprecated in favor of checking if + ``Model._meta.auto_field is not None``. diff --git a/tests/model_meta/test_removedindjango21.py b/tests/model_meta/test_removedindjango21.py new file mode 100644 index 0000000000..0e028c4f29 --- /dev/null +++ b/tests/model_meta/test_removedindjango21.py @@ -0,0 +1,22 @@ +import warnings + +from django.test import SimpleTestCase + +from .models import Person + + +class HasAutoFieldTests(SimpleTestCase): + + def test_get_warns(self): + with warnings.catch_warnings(record=True) as warns: + warnings.simplefilter('always') + Person._meta.has_auto_field + self.assertEqual(len(warns), 1) + self.assertEqual( + str(warns[0].message), + 'Model._meta.has_auto_field is deprecated in favor of checking if ' + 'Model._meta.auto_field is not None.', + ) + + def test_set_does_nothing(self): + Person._meta.has_auto_field = True