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
import copy
import warnings
from collections import OrderedDict
from contextlib import contextmanager
......@@ -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.utils import make_model_tuple
from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import force_text
from django.utils.functional import cached_property
from django.utils.module_loading import import_string
......@@ -604,18 +602,8 @@ class ModelState(object):
# Restore 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__)
return type(
str(self.name),
bases,
body,
)
# Then, make a Model object (apps.register_model is called in __new__)
return type(str(self.name), bases, body)
def get_field_by_name(self, name):
for fname, field in self.fields:
......
......@@ -29,7 +29,6 @@ from django.db.models.signals import (
)
from django.db.models.utils import make_model_tuple
from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import (
force_str, force_text, python_2_unicode_compatible,
)
......@@ -358,7 +357,7 @@ class ModelBase(type):
if 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):
raise ValueError(
"Model %s must specify a custom Manager, because it has a "
......@@ -370,79 +369,6 @@ class ModelBase(type):
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
def _base_manager(cls):
return cls._meta.base_manager
......
......@@ -65,13 +65,11 @@ and two directions (forward and reverse) for a total of six combinations.
from __future__ import unicode_literals
import warnings
from operator import attrgetter
from django.db import connections, router, transaction
from django.db.models import Q, signals
from django.db.models.query import QuerySet
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.functional import cached_property
......@@ -107,20 +105,7 @@ class ForwardManyToOneDescriptor(object):
return hasattr(instance, self.cache_name)
def get_queryset(self, **hints):
related_model = self.field.remote_field.model
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()
return self.field.remote_field.model._base_manager.db_manager(hints=hints).all()
def get_prefetch_queryset(self, instances, queryset=None):
if queryset is None:
......@@ -323,20 +308,7 @@ class ReverseOneToOneDescriptor(object):
return hasattr(instance, self.cache_name)
def get_queryset(self, **hints):
related_model = self.related.related_model
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()
return self.related.related_model._base_manager.db_manager(hints=hints).all()
def get_prefetch_queryset(self, instances, queryset=None):
if queryset is None:
......
......@@ -17,9 +17,7 @@ from django.db.models.fields.related import OneToOneField
from django.db.models.query_utils import PathInfo
from django.utils import six
from django.utils.datastructures import ImmutableList, OrderedSet
from django.utils.deprecation import (
RemovedInDjango20Warning, RemovedInDjango21Warning,
)
from django.utils.deprecation import RemovedInDjango21Warning
from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.functional import cached_property
from django.utils.text import camel_case_to_spaces, format_lazy
......@@ -41,7 +39,7 @@ DEFAULT_NAMES = (
'auto_created', 'index_together', 'apps', 'default_permissions',
'select_on_save', 'default_related_name', 'required_db_features',
'required_db_vendor', 'base_manager_name', 'default_manager_name',
'manager_inheritance_from_future', 'indexes',
'indexes',
)
......@@ -87,7 +85,6 @@ class Options(object):
self.local_fields = []
self.local_many_to_many = []
self.private_fields = []
self.manager_inheritance_from_future = False
self.local_managers = []
self.base_manager_name = None
self.default_manager_name = None
......@@ -375,10 +372,6 @@ class Options(object):
seen_managers.add(manager.name)
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(
"managers",
(m[2] for m in sorted(managers)),
......@@ -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.name = '_base_manager'
manager.model = self.model
......
......@@ -384,3 +384,9 @@ these features.
removed.
* 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):
class Child6(Child4):
value = models.IntegerField()
class Meta:
manager_inheritance_from_future = True
class Child7(Parent):
objects = models.Manager()
......
This diff is collapsed.
......@@ -4,8 +4,7 @@ from copy import deepcopy
from django.core.exceptions import FieldError, MultipleObjectsReturned
from django.db import models, transaction
from django.db.utils import IntegrityError
from django.test import TestCase, ignore_warnings
from django.utils.deprecation import RemovedInDjango20Warning
from django.test import TestCase
from django.utils.translation import ugettext_lazy
from .models import (
......@@ -577,7 +576,6 @@ class ManyToOneTests(TestCase):
with self.assertNumQueries(1):
self.assertEqual(th.child_set.count(), 0)
@ignore_warnings(category=RemovedInDjango20Warning) # for use_for_related_fields deprecation
def test_related_object(self):
public_school = School.objects.create(is_public=True)
public_student = Student.objects.create(school=public_school)
......@@ -595,17 +593,6 @@ class ManyToOneTests(TestCase):
# allow it.
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._expire_cache()
try:
......
from __future__ import unicode_literals
from django.db import IntegrityError, connection, transaction
from django.test import TestCase, ignore_warnings
from django.utils.deprecation import RemovedInDjango20Warning
from django.test import TestCase
from .models import (
Bar, Director, Favorites, HiddenPointer, ManualPrimaryKey, MultiModel,
......@@ -419,7 +418,6 @@ class OneToOneTests(TestCase):
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):
public_school = School.objects.create(is_public=True)
public_director = Director.objects.create(school=public_school, is_temp=False)
......@@ -452,25 +450,6 @@ class OneToOneTests(TestCase):
# allow it.
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._expire_cache()
try:
......
......@@ -17,6 +17,3 @@ class Parent(models.Model):
class Child(Parent):
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