1
0
mirror of https://github.com/django/django.git synced 2025-10-24 14:16:09 +00:00

Fixed #24215 -- Refactored lazy model operations

This adds a new method, Apps.lazy_model_operation(), and a helper function,
lazy_related_operation(), which together supersede add_lazy_relation() and
make lazy model operations the responsibility of the App registry. This
system no longer uses the class_prepared signal.
This commit is contained in:
Alex Hill
2015-03-03 16:43:56 +08:00
committed by Tim Graham
parent 0f6f80c2e7
commit 720ff740e7
10 changed files with 231 additions and 165 deletions

View File

@@ -5,6 +5,7 @@ import unittest
from decimal import Decimal
from django import forms, test
from django.apps import apps
from django.core import checks, validators
from django.core.exceptions import ValidationError
from django.db import IntegrityError, connection, models, transaction
@@ -21,12 +22,11 @@ from django.utils import six
from django.utils.functional import lazy
from .models import (
AbstractForeignFieldsModel, Bar, BigD, BigIntegerModel, BigS, BooleanModel,
DataModel, DateTimeModel, Document, FksToBooleans, FkToChar, FloatModel,
Foo, GenericIPAddress, IntegerModel, NullBooleanModel,
PositiveIntegerModel, PositiveSmallIntegerModel, Post, PrimaryKeyCharModel,
RenamedField, SmallIntegerModel, VerboseNameField, Whiz, WhizIter,
WhizIterEmpty,
Bar, BigD, BigIntegerModel, BigS, BooleanModel, DataModel, DateTimeModel,
Document, FksToBooleans, FkToChar, FloatModel, Foo, GenericIPAddress,
IntegerModel, NullBooleanModel, PositiveIntegerModel,
PositiveSmallIntegerModel, Post, PrimaryKeyCharModel, RenamedField,
SmallIntegerModel, VerboseNameField, Whiz, WhizIter, WhizIterEmpty,
)
@@ -202,37 +202,46 @@ class ForeignKeyTests(test.TestCase):
rel_name = Bar._meta.get_field('a').remote_field.related_name
self.assertIsInstance(rel_name, six.text_type)
def test_abstract_model_pending_lookups(self):
def test_abstract_model_pending_operations(self):
"""
Foreign key fields declared on abstract models should not add lazy relations to
resolve relationship declared as string. refs #24215
"""
opts = AbstractForeignFieldsModel._meta
to_key = ('missing', 'FK')
fk_lookup = (AbstractForeignFieldsModel, opts.get_field('fk'))
self.assertFalse(
any(lookup[0:2] == fk_lookup for lookup in opts.apps._pending_lookups.get(to_key, [])),
'Pending lookup added for the abstract model foreign key `to` parameter'
pending_ops_before = list(apps._pending_operations.items())
class AbstractForeignKeyModel(models.Model):
fk = models.ForeignKey('missing.FK')
class Meta:
abstract = True
self.assertIs(AbstractForeignKeyModel._meta.apps, apps)
self.assertEqual(
pending_ops_before,
list(apps._pending_operations.items()),
"Pending lookup added for a foreign key on an abstract model"
)
class ManyToManyFieldTests(test.TestCase):
def test_abstract_model_pending_lookups(self):
def test_abstract_model_pending_operations(self):
"""
Many-to-many fields declared on abstract models should not add lazy relations to
resolve relationship declared as string. refs #24215
"""
opts = AbstractForeignFieldsModel._meta
to_key = ('missing', 'M2M')
fk_lookup = (AbstractForeignFieldsModel, opts.get_field('m2m'))
self.assertFalse(
any(lookup[0:2] == fk_lookup for lookup in opts.apps._pending_lookups.get(to_key, [])),
'Pending lookup added for the abstract model many-to-many `to` parameter.'
)
through_key = ('missing', 'Through')
self.assertFalse(
any(lookup[0:2] == fk_lookup for lookup in opts.apps._pending_lookups.get(through_key, [])),
'Pending lookup added for the abstract model many-to-many `through` parameter.'
pending_ops_before = list(apps._pending_operations.items())
class AbstractManyToManyModel(models.Model):
fk = models.ForeignKey('missing.FK')
class Meta:
abstract = True
self.assertIs(AbstractManyToManyModel._meta.apps, apps)
self.assertEqual(
pending_ops_before,
list(apps._pending_operations.items()),
"Pending lookup added for a many-to-many field on an abstract model"
)