Kaydet (Commit) 631f4ab0 authored tarafından Tim Graham's avatar Tim Graham

Removed Manager.use_for_related_fields and Meta.manager_inheritance_from_future.

Per deprecation timeline. Refs ed0ff913.
üst 60ca37d2
from __future__ import unicode_literals from __future__ import unicode_literals
import copy import copy
import warnings
from collections import OrderedDict from collections import OrderedDict
from contextlib import contextmanager from contextlib import contextmanager
...@@ -14,7 +13,6 @@ from django.db.models.fields.related import RECURSIVE_RELATIONSHIP_CONSTANT ...@@ -14,7 +13,6 @@ from django.db.models.fields.related import RECURSIVE_RELATIONSHIP_CONSTANT
from django.db.models.options import DEFAULT_NAMES, normalize_together from django.db.models.options import DEFAULT_NAMES, normalize_together
from django.db.models.utils import make_model_tuple from django.db.models.utils import make_model_tuple
from django.utils import six from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.module_loading import import_string from django.utils.module_loading import import_string
...@@ -604,18 +602,8 @@ class ModelState(object): ...@@ -604,18 +602,8 @@ class ModelState(object):
# Restore managers # Restore managers
body.update(self.construct_managers()) body.update(self.construct_managers())
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore", "Managers from concrete parents will soon qualify as default managers",
RemovedInDjango20Warning)
# Then, make a Model object (apps.register_model is called in __new__) # Then, make a Model object (apps.register_model is called in __new__)
return type( return type(str(self.name), bases, body)
str(self.name),
bases,
body,
)
def get_field_by_name(self, name): def get_field_by_name(self, name):
for fname, field in self.fields: for fname, field in self.fields:
......
...@@ -29,7 +29,6 @@ from django.db.models.signals import ( ...@@ -29,7 +29,6 @@ from django.db.models.signals import (
) )
from django.db.models.utils import make_model_tuple from django.db.models.utils import make_model_tuple
from django.utils import six from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import ( from django.utils.encoding import (
force_str, force_text, python_2_unicode_compatible, force_str, force_text, python_2_unicode_compatible,
) )
...@@ -358,7 +357,7 @@ class ModelBase(type): ...@@ -358,7 +357,7 @@ class ModelBase(type):
if get_absolute_url_override: if get_absolute_url_override:
setattr(cls, 'get_absolute_url', get_absolute_url_override) setattr(cls, 'get_absolute_url', get_absolute_url_override)
if not opts.managers or cls._requires_legacy_default_manager(): if not opts.managers:
if any(f.name == 'objects' for f in opts.fields): if any(f.name == 'objects' for f in opts.fields):
raise ValueError( raise ValueError(
"Model %s must specify a custom Manager, because it has a " "Model %s must specify a custom Manager, because it has a "
...@@ -370,79 +369,6 @@ class ModelBase(type): ...@@ -370,79 +369,6 @@ class ModelBase(type):
class_prepared.send(sender=cls) class_prepared.send(sender=cls)
def _requires_legacy_default_manager(cls): # RemovedInDjango20Warning
opts = cls._meta
if opts.manager_inheritance_from_future:
return False
future_default_manager = opts.default_manager
# Step 1: Locate a manager that would have been promoted
# to default manager with the legacy system.
for manager in opts.managers:
originating_model = manager._originating_model
if (cls is originating_model or cls._meta.proxy or
originating_model._meta.abstract):
if manager is not cls._default_manager and not opts.default_manager_name:
warnings.warn(
"Managers from concrete parents will soon qualify as default "
"managers if they appear before any other managers in the "
"MRO. As a result, '{legacy_default_manager}' declared on "
"'{legacy_default_manager_model}' will no longer be the "
"default manager for '{model}' in favor of "
"'{future_default_manager}' declared on "
"'{future_default_manager_model}'. "
"You can redeclare '{legacy_default_manager}' on '{cls}' "
"to keep things the way they are or you can switch to the new "
"behavior right away by setting "
"`Meta.manager_inheritance_from_future` to `True`.".format(
cls=cls.__name__,
model=opts.label,
legacy_default_manager=manager.name,
legacy_default_manager_model=manager._originating_model._meta.label,
future_default_manager=future_default_manager.name,
future_default_manager_model=future_default_manager._originating_model._meta.label,
),
RemovedInDjango20Warning, 2
)
opts.default_manager_name = manager.name
opts._expire_cache()
break
# Step 2: Since there are managers but none of them qualified as
# default managers under the legacy system (meaning that there are
# managers from concrete parents that would be promoted under the
# new system), we need to create a new Manager instance for the
# 'objects' attribute as a deprecation shim.
else:
# If the "future" default manager was auto created there is no
# point warning the user since it's basically the same manager.
if not future_default_manager.auto_created:
warnings.warn(
"Managers from concrete parents will soon qualify as "
"default managers. As a result, the 'objects' manager "
"won't be created (or recreated) automatically "
"anymore on '{model}' and '{future_default_manager}' "
"declared on '{future_default_manager_model}' will be "
"promoted to default manager. You can declare "
"explicitly `objects = models.Manager()` on '{cls}' "
"to keep things the way they are or you can switch "
"to the new behavior right away by setting "
"`Meta.manager_inheritance_from_future` to `True`.".format(
cls=cls.__name__,
model=opts.label,
future_default_manager=future_default_manager.name,
future_default_manager_model=future_default_manager._originating_model._meta.label,
),
RemovedInDjango20Warning, 2
)
return True
@property @property
def _base_manager(cls): def _base_manager(cls):
return cls._meta.base_manager return cls._meta.base_manager
......
...@@ -65,13 +65,11 @@ and two directions (forward and reverse) for a total of six combinations. ...@@ -65,13 +65,11 @@ and two directions (forward and reverse) for a total of six combinations.
from __future__ import unicode_literals from __future__ import unicode_literals
import warnings
from operator import attrgetter from operator import attrgetter
from django.db import connections, router, transaction from django.db import connections, router, transaction
from django.db.models import Q, signals from django.db.models import Q, signals
from django.db.models.query import QuerySet from django.db.models.query import QuerySet
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.functional import cached_property from django.utils.functional import cached_property
...@@ -107,20 +105,7 @@ class ForwardManyToOneDescriptor(object): ...@@ -107,20 +105,7 @@ class ForwardManyToOneDescriptor(object):
return hasattr(instance, self.cache_name) return hasattr(instance, self.cache_name)
def get_queryset(self, **hints): def get_queryset(self, **hints):
related_model = self.field.remote_field.model return self.field.remote_field.model._base_manager.db_manager(hints=hints).all()
if getattr(related_model._default_manager, 'use_for_related_fields', False):
if not getattr(related_model._default_manager, 'silence_use_for_related_fields_deprecation', False):
warnings.warn(
"use_for_related_fields is deprecated, instead "
"set Meta.base_manager_name on '{}'.".format(related_model._meta.label),
RemovedInDjango20Warning, 2
)
manager = related_model._default_manager
else:
manager = related_model._base_manager
return manager.db_manager(hints=hints).all()
def get_prefetch_queryset(self, instances, queryset=None): def get_prefetch_queryset(self, instances, queryset=None):
if queryset is None: if queryset is None:
...@@ -323,20 +308,7 @@ class ReverseOneToOneDescriptor(object): ...@@ -323,20 +308,7 @@ class ReverseOneToOneDescriptor(object):
return hasattr(instance, self.cache_name) return hasattr(instance, self.cache_name)
def get_queryset(self, **hints): def get_queryset(self, **hints):
related_model = self.related.related_model return self.related.related_model._base_manager.db_manager(hints=hints).all()
if getattr(related_model._default_manager, 'use_for_related_fields', False):
if not getattr(related_model._default_manager, 'silence_use_for_related_fields_deprecation', False):
warnings.warn(
"use_for_related_fields is deprecated, instead "
"set Meta.base_manager_name on '{}'.".format(related_model._meta.label),
RemovedInDjango20Warning, 2
)
manager = related_model._default_manager
else:
manager = related_model._base_manager
return manager.db_manager(hints=hints).all()
def get_prefetch_queryset(self, instances, queryset=None): def get_prefetch_queryset(self, instances, queryset=None):
if queryset is None: if queryset is None:
......
...@@ -17,9 +17,7 @@ from django.db.models.fields.related import OneToOneField ...@@ -17,9 +17,7 @@ from django.db.models.fields.related import OneToOneField
from django.db.models.query_utils import PathInfo from django.db.models.query_utils import PathInfo
from django.utils import six from django.utils import six
from django.utils.datastructures import ImmutableList, OrderedSet from django.utils.datastructures import ImmutableList, OrderedSet
from django.utils.deprecation import ( from django.utils.deprecation import RemovedInDjango21Warning
RemovedInDjango20Warning, RemovedInDjango21Warning,
)
from django.utils.encoding import force_text, python_2_unicode_compatible from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.text import camel_case_to_spaces, format_lazy from django.utils.text import camel_case_to_spaces, format_lazy
...@@ -41,7 +39,7 @@ DEFAULT_NAMES = ( ...@@ -41,7 +39,7 @@ DEFAULT_NAMES = (
'auto_created', 'index_together', 'apps', 'default_permissions', 'auto_created', 'index_together', 'apps', 'default_permissions',
'select_on_save', 'default_related_name', 'required_db_features', 'select_on_save', 'default_related_name', 'required_db_features',
'required_db_vendor', 'base_manager_name', 'default_manager_name', 'required_db_vendor', 'base_manager_name', 'default_manager_name',
'manager_inheritance_from_future', 'indexes', 'indexes',
) )
...@@ -87,7 +85,6 @@ class Options(object): ...@@ -87,7 +85,6 @@ class Options(object):
self.local_fields = [] self.local_fields = []
self.local_many_to_many = [] self.local_many_to_many = []
self.private_fields = [] self.private_fields = []
self.manager_inheritance_from_future = False
self.local_managers = [] self.local_managers = []
self.base_manager_name = None self.base_manager_name = None
self.default_manager_name = None self.default_manager_name = None
...@@ -375,10 +372,6 @@ class Options(object): ...@@ -375,10 +372,6 @@ class Options(object):
seen_managers.add(manager.name) seen_managers.add(manager.name)
managers.append((depth, manager.creation_counter, manager)) managers.append((depth, manager.creation_counter, manager))
# Used for deprecation of legacy manager inheritance,
# remove afterwards. (RemovedInDjango20Warning)
manager._originating_model = base
return make_immutable_fields_list( return make_immutable_fields_list(
"managers", "managers",
(m[2] for m in sorted(managers)), (m[2] for m in sorted(managers)),
...@@ -410,25 +403,6 @@ class Options(object): ...@@ -410,25 +403,6 @@ class Options(object):
) )
) )
# Deprecation shim for `use_for_related_fields`.
for i, base_manager_class in enumerate(self.default_manager.__class__.mro()):
if getattr(base_manager_class, 'use_for_related_fields', False):
if not getattr(base_manager_class, 'silence_use_for_related_fields_deprecation', False):
warnings.warn(
"use_for_related_fields is deprecated, instead "
"set Meta.base_manager_name on '{}'.".format(self.model._meta.label),
RemovedInDjango20Warning, 2
)
if i == 0:
manager = self.default_manager
else:
manager = base_manager_class()
manager.name = '_base_manager'
manager.model = self.model
return manager
manager = Manager() manager = Manager()
manager.name = '_base_manager' manager.name = '_base_manager'
manager.model = self.model manager.model = self.model
......
...@@ -384,3 +384,9 @@ these features. ...@@ -384,3 +384,9 @@ these features.
removed. removed.
* The ``escape`` filter now uses ``django.utils.html.conditional_escape()``. * The ``escape`` filter now uses ``django.utils.html.conditional_escape()``.
* ``Manager.use_for_related_fields`` is removed.
* Model ``Manager`` inheritance follows MRO inheritance rules. The requirement
to use ``Meta.manager_inheritance_from_future`` to opt-in to the behavior is
removed.
...@@ -118,9 +118,6 @@ class Child5(AbstractBase3): ...@@ -118,9 +118,6 @@ class Child5(AbstractBase3):
class Child6(Child4): class Child6(Child4):
value = models.IntegerField() value = models.IntegerField()
class Meta:
manager_inheritance_from_future = True
class Child7(Parent): class Child7(Parent):
objects = models.Manager() objects = models.Manager()
......
This diff is collapsed.
...@@ -4,8 +4,7 @@ from copy import deepcopy ...@@ -4,8 +4,7 @@ from copy import deepcopy
from django.core.exceptions import FieldError, MultipleObjectsReturned from django.core.exceptions import FieldError, MultipleObjectsReturned
from django.db import models, transaction from django.db import models, transaction
from django.db.utils import IntegrityError from django.db.utils import IntegrityError
from django.test import TestCase, ignore_warnings from django.test import TestCase
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.translation import ugettext_lazy from django.utils.translation import ugettext_lazy
from .models import ( from .models import (
...@@ -577,7 +576,6 @@ class ManyToOneTests(TestCase): ...@@ -577,7 +576,6 @@ class ManyToOneTests(TestCase):
with self.assertNumQueries(1): with self.assertNumQueries(1):
self.assertEqual(th.child_set.count(), 0) self.assertEqual(th.child_set.count(), 0)
@ignore_warnings(category=RemovedInDjango20Warning) # for use_for_related_fields deprecation
def test_related_object(self): def test_related_object(self):
public_school = School.objects.create(is_public=True) public_school = School.objects.create(is_public=True)
public_student = Student.objects.create(school=public_school) public_student = Student.objects.create(school=public_school)
...@@ -595,17 +593,6 @@ class ManyToOneTests(TestCase): ...@@ -595,17 +593,6 @@ class ManyToOneTests(TestCase):
# allow it. # allow it.
self.assertEqual(private_student.school, private_school) self.assertEqual(private_student.school, private_school)
# If the manager is marked "use_for_related_fields", it'll get used instead
# of the "bare" queryset. Usually you'd define this as a property on the class,
# but this approximates that in a way that's easier in tests.
School._default_manager.use_for_related_fields = True
try:
private_student = Student.objects.get(pk=private_student.pk)
with self.assertRaises(School.DoesNotExist):
private_student.school
finally:
School._default_manager.use_for_related_fields = False
School._meta.base_manager_name = 'objects' School._meta.base_manager_name = 'objects'
School._meta._expire_cache() School._meta._expire_cache()
try: try:
......
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import IntegrityError, connection, transaction from django.db import IntegrityError, connection, transaction
from django.test import TestCase, ignore_warnings from django.test import TestCase
from django.utils.deprecation import RemovedInDjango20Warning
from .models import ( from .models import (
Bar, Director, Favorites, HiddenPointer, ManualPrimaryKey, MultiModel, Bar, Director, Favorites, HiddenPointer, ManualPrimaryKey, MultiModel,
...@@ -419,7 +418,6 @@ class OneToOneTests(TestCase): ...@@ -419,7 +418,6 @@ class OneToOneTests(TestCase):
hasattr(Target, HiddenPointer._meta.get_field('target').remote_field.get_accessor_name()) hasattr(Target, HiddenPointer._meta.get_field('target').remote_field.get_accessor_name())
) )
@ignore_warnings(category=RemovedInDjango20Warning) # for use_for_related_fields deprecation
def test_related_object(self): def test_related_object(self):
public_school = School.objects.create(is_public=True) public_school = School.objects.create(is_public=True)
public_director = Director.objects.create(school=public_school, is_temp=False) public_director = Director.objects.create(school=public_school, is_temp=False)
...@@ -452,25 +450,6 @@ class OneToOneTests(TestCase): ...@@ -452,25 +450,6 @@ class OneToOneTests(TestCase):
# allow it. # allow it.
self.assertEqual(private_school.director, private_director) self.assertEqual(private_school.director, private_director)
# If the manager is marked "use_for_related_fields", it'll get used instead
# of the "bare" queryset. Usually you'd define this as a property on the class,
# but this approximates that in a way that's easier in tests.
School._default_manager.use_for_related_fields = True
try:
private_director = Director._base_manager.get(pk=private_director.pk)
with self.assertRaises(School.DoesNotExist):
private_director.school
finally:
School._default_manager.use_for_related_fields = False
Director._default_manager.use_for_related_fields = True
try:
private_school = School._base_manager.get(pk=private_school.pk)
with self.assertRaises(Director.DoesNotExist):
private_school.director
finally:
Director._default_manager.use_for_related_fields = False
School._meta.base_manager_name = 'objects' School._meta.base_manager_name = 'objects'
School._meta._expire_cache() School._meta._expire_cache()
try: try:
......
...@@ -17,6 +17,3 @@ class Parent(models.Model): ...@@ -17,6 +17,3 @@ class Parent(models.Model):
class Child(Parent): class Child(Parent):
child_data = models.CharField(max_length=30, unique=True) child_data = models.CharField(max_length=30, unique=True)
class Meta:
manager_inheritance_from_future = True
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment