Kaydet (Commit) e542e81b authored tarafından Aymeric Augustin's avatar Aymeric Augustin

Renamed descriptor classes for related objects.

The old names were downright confusing. Some seemed to mean the opposite
of what the class actually did.

The new names follow a consistent nomenclature:

    (Forward|Reverse)(ManyToOne|OneToOne|ManyToMany)Descriptor.

I mentioned combinations that do not exist in the docstring in order to
help people who would search for them in the code base.
üst 2409a424
...@@ -9,7 +9,7 @@ from django.db import DEFAULT_DB_ALIAS, connection, models, router, transaction ...@@ -9,7 +9,7 @@ from django.db import DEFAULT_DB_ALIAS, connection, models, router, transaction
from django.db.models import DO_NOTHING, signals from django.db.models import DO_NOTHING, signals
from django.db.models.base import ModelBase, make_foreign_order_accessors from django.db.models.base import ModelBase, make_foreign_order_accessors
from django.db.models.fields.related import ( from django.db.models.fields.related import (
ForeignObject, ForeignObjectRel, ForeignRelatedObjectsDescriptor, ForeignObject, ForeignObjectRel, ReverseManyToOneDescriptor,
lazy_related_operation, lazy_related_operation,
) )
from django.db.models.query_utils import PathInfo from django.db.models.query_utils import PathInfo
...@@ -24,8 +24,7 @@ class GenericForeignKey(object): ...@@ -24,8 +24,7 @@ class GenericForeignKey(object):
``object_id`` fields. ``object_id`` fields.
This class also doubles as an accessor to the related object (similar to This class also doubles as an accessor to the related object (similar to
ReverseSingleRelatedObjectDescriptor) by adding itself as a model ForwardManyToOneDescriptor) by adding itself as a model attribute.
attribute.
""" """
# Field flags # Field flags
...@@ -381,7 +380,7 @@ class GenericRelation(ForeignObject): ...@@ -381,7 +380,7 @@ class GenericRelation(ForeignObject):
kwargs['virtual_only'] = True kwargs['virtual_only'] = True
super(GenericRelation, self).contribute_to_class(cls, name, **kwargs) super(GenericRelation, self).contribute_to_class(cls, name, **kwargs)
self.model = cls self.model = cls
setattr(cls, self.name, ReverseGenericRelatedObjectsDescriptor(self.remote_field)) setattr(cls, self.name, ReverseGenericManyToOneDescriptor(self.remote_field))
# Add get_RELATED_order() and set_RELATED_order() methods if the model # Add get_RELATED_order() and set_RELATED_order() methods if the model
# on the other end of this relation is ordered with respect to this. # on the other end of this relation is ordered with respect to this.
...@@ -430,7 +429,7 @@ class GenericRelation(ForeignObject): ...@@ -430,7 +429,7 @@ class GenericRelation(ForeignObject):
}) })
class ReverseGenericRelatedObjectsDescriptor(ForeignRelatedObjectsDescriptor): class ReverseGenericManyToOneDescriptor(ReverseManyToOneDescriptor):
""" """
Accessor to the related objects manager on the one-to-many relation created Accessor to the related objects manager on the one-to-many relation created
by GenericRelation. by GenericRelation.
...@@ -440,7 +439,7 @@ class ReverseGenericRelatedObjectsDescriptor(ForeignRelatedObjectsDescriptor): ...@@ -440,7 +439,7 @@ class ReverseGenericRelatedObjectsDescriptor(ForeignRelatedObjectsDescriptor):
class Post(Model): class Post(Model):
comments = GenericRelation(Comment) comments = GenericRelation(Comment)
``post.comments`` is a ReverseGenericRelatedObjectsDescriptor instance. ``post.comments`` is a ReverseGenericManyToOneDescriptor instance.
""" """
@cached_property @cached_property
......
...@@ -25,8 +25,8 @@ from . import ( ...@@ -25,8 +25,8 @@ from . import (
PositiveSmallIntegerField, PositiveSmallIntegerField,
) )
from .related_descriptors import ( from .related_descriptors import (
ForeignRelatedObjectsDescriptor, ManyRelatedObjectsDescriptor, ForwardManyToOneDescriptor, ManyToManyDescriptor,
ReverseSingleRelatedObjectDescriptor, SingleRelatedObjectDescriptor, ReverseManyToOneDescriptor, ReverseOneToOneDescriptor,
) )
from .related_lookups import ( from .related_lookups import (
RelatedExact, RelatedGreaterThan, RelatedGreaterThanOrEqual, RelatedIn, RelatedExact, RelatedGreaterThan, RelatedGreaterThanOrEqual, RelatedIn,
...@@ -432,7 +432,7 @@ class ForeignObject(RelatedField): ...@@ -432,7 +432,7 @@ class ForeignObject(RelatedField):
one_to_one = False one_to_one = False
requires_unique_target = True requires_unique_target = True
related_accessor_class = ForeignRelatedObjectsDescriptor related_accessor_class = ReverseManyToOneDescriptor
rel_class = ForeignObjectRel rel_class = ForeignObjectRel
def __init__(self, to, on_delete, from_fields, to_fields, rel=None, related_name=None, def __init__(self, to, on_delete, from_fields, to_fields, rel=None, related_name=None,
...@@ -684,7 +684,7 @@ class ForeignObject(RelatedField): ...@@ -684,7 +684,7 @@ class ForeignObject(RelatedField):
def contribute_to_class(self, cls, name, virtual_only=False): def contribute_to_class(self, cls, name, virtual_only=False):
super(ForeignObject, self).contribute_to_class(cls, name, virtual_only=virtual_only) super(ForeignObject, self).contribute_to_class(cls, name, virtual_only=virtual_only)
setattr(cls, self.name, ReverseSingleRelatedObjectDescriptor(self)) setattr(cls, self.name, ForwardManyToOneDescriptor(self))
def contribute_to_related_class(self, cls, related): def contribute_to_related_class(self, cls, related):
# Internal FK's - i.e., those with a related name ending with '+' - # Internal FK's - i.e., those with a related name ending with '+' -
...@@ -974,7 +974,7 @@ class OneToOneField(ForeignKey): ...@@ -974,7 +974,7 @@ class OneToOneField(ForeignKey):
one_to_many = False one_to_many = False
one_to_one = True one_to_one = True
related_accessor_class = SingleRelatedObjectDescriptor related_accessor_class = ReverseOneToOneDescriptor
rel_class = OneToOneRel rel_class = OneToOneRel
description = _("One-to-one relationship") description = _("One-to-one relationship")
...@@ -1560,7 +1560,7 @@ class ManyToManyField(RelatedField): ...@@ -1560,7 +1560,7 @@ class ManyToManyField(RelatedField):
self.remote_field.through = create_many_to_many_intermediary_model(self, cls) self.remote_field.through = create_many_to_many_intermediary_model(self, cls)
# Add the descriptor for the m2m relation. # Add the descriptor for the m2m relation.
setattr(cls, self.name, ManyRelatedObjectsDescriptor(self.remote_field, reverse=False)) setattr(cls, self.name, ManyToManyDescriptor(self.remote_field, reverse=False))
# Set up the accessor for the m2m table name for the relation. # Set up the accessor for the m2m table name for the relation.
self.m2m_db_table = curry(self._get_m2m_db_table, cls._meta) self.m2m_db_table = curry(self._get_m2m_db_table, cls._meta)
...@@ -1569,7 +1569,7 @@ class ManyToManyField(RelatedField): ...@@ -1569,7 +1569,7 @@ class ManyToManyField(RelatedField):
# Internal M2Ms (i.e., those with a related name ending with '+') # Internal M2Ms (i.e., those with a related name ending with '+')
# and swapped models don't get a related descriptor. # and swapped models don't get a related descriptor.
if not self.remote_field.is_hidden() and not related.related_model._meta.swapped: if not self.remote_field.is_hidden() and not related.related_model._meta.swapped:
setattr(cls, related.get_accessor_name(), ManyRelatedObjectsDescriptor(self.remote_field, reverse=True)) setattr(cls, related.get_accessor_name(), ManyToManyDescriptor(self.remote_field, reverse=True))
# Set up the accessors for the column names on the m2m table. # Set up the accessors for the column names on the m2m table.
self.m2m_column_name = curry(self._get_m2m_attr, related, 'column') self.m2m_column_name = curry(self._get_m2m_attr, related, 'column')
......
from django.db import models from django.db import models
from django.db.models.fields.related import \ from django.db.models.fields.related import ForwardManyToOneDescriptor
ReverseSingleRelatedObjectDescriptor
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import get_language from django.utils.translation import get_language
class ArticleTranslationDescriptor(ReverseSingleRelatedObjectDescriptor): class ArticleTranslationDescriptor(ForwardManyToOneDescriptor):
""" """
The set of articletranslation should not set any local fields. The set of articletranslation should not set any local fields.
""" """
......
from django.db import models from django.db import models
from django.db.models.fields.related import ( from django.db.models.fields.related import (
ForeignObjectRel, ForeignRelatedObjectsDescriptor, ForeignObjectRel, ReverseManyToOneDescriptor,
) )
from django.db.models.lookups import StartsWith from django.db.models.lookups import StartsWith
from django.db.models.query_utils import PathInfo from django.db.models.query_utils import PathInfo
...@@ -10,7 +10,7 @@ from django.utils.encoding import python_2_unicode_compatible ...@@ -10,7 +10,7 @@ from django.utils.encoding import python_2_unicode_compatible
class CustomForeignObjectRel(ForeignObjectRel): class CustomForeignObjectRel(ForeignObjectRel):
""" """
Define some extra Field methods so this Rel acts more like a Field, which Define some extra Field methods so this Rel acts more like a Field, which
lets us use ForeignRelatedObjectsDescriptor in both directions. lets us use ReverseManyToOneDescriptor in both directions.
""" """
@property @property
def foreign_related_fields(self): def foreign_related_fields(self):
...@@ -24,7 +24,7 @@ class StartsWithRelation(models.ForeignObject): ...@@ -24,7 +24,7 @@ class StartsWithRelation(models.ForeignObject):
""" """
A ForeignObject that uses StartsWith operator in its joins instead of A ForeignObject that uses StartsWith operator in its joins instead of
the default equality operator. This is logically a many-to-many relation the default equality operator. This is logically a many-to-many relation
and creates a ForeignRelatedObjectsDescriptor in both directions. and creates a ReverseManyToOneDescriptor in both directions.
""" """
auto_created = False auto_created = False
...@@ -42,7 +42,7 @@ class StartsWithRelation(models.ForeignObject): ...@@ -42,7 +42,7 @@ class StartsWithRelation(models.ForeignObject):
@property @property
def field(self): def field(self):
""" """
Makes ForeignRelatedObjectsDescriptor work in both directions. Makes ReverseManyToOneDescriptor work in both directions.
""" """
return self.remote_field return self.remote_field
...@@ -66,7 +66,7 @@ class StartsWithRelation(models.ForeignObject): ...@@ -66,7 +66,7 @@ class StartsWithRelation(models.ForeignObject):
def contribute_to_class(self, cls, name, virtual_only=False): def contribute_to_class(self, cls, name, virtual_only=False):
super(StartsWithRelation, self).contribute_to_class(cls, name, virtual_only) super(StartsWithRelation, self).contribute_to_class(cls, name, virtual_only)
setattr(cls, self.name, ForeignRelatedObjectsDescriptor(self)) setattr(cls, self.name, ReverseManyToOneDescriptor(self))
class BrokenContainsRelation(StartsWithRelation): class BrokenContainsRelation(StartsWithRelation):
......
...@@ -329,7 +329,7 @@ class GenericRelationsTests(TestCase): ...@@ -329,7 +329,7 @@ class GenericRelationsTests(TestCase):
def test_assign_with_queryset(self): def test_assign_with_queryset(self):
# Ensure that querysets used in reverse GFK assignments are pre-evaluated # Ensure that querysets used in reverse GFK assignments are pre-evaluated
# so their value isn't affected by the clearing operation in # so their value isn't affected by the clearing operation in
# ManyRelatedObjectsDescriptor.__set__. Refs #19816. # ManyToManyDescriptor.__set__. Refs #19816.
bacon = Vegetable.objects.create(name="Bacon", is_yucky=False) bacon = Vegetable.objects.create(name="Bacon", is_yucky=False)
bacon.tags.create(tag="fatty") bacon.tags.create(tag="fatty")
bacon.tags.create(tag="salty") bacon.tags.create(tag="salty")
......
...@@ -412,7 +412,7 @@ class ManyToManyTests(TestCase): ...@@ -412,7 +412,7 @@ class ManyToManyTests(TestCase):
def test_forward_assign_with_queryset(self): def test_forward_assign_with_queryset(self):
# Ensure that querysets used in m2m assignments are pre-evaluated # Ensure that querysets used in m2m assignments are pre-evaluated
# so their value isn't affected by the clearing operation in # so their value isn't affected by the clearing operation in
# ManyRelatedObjectsDescriptor.__set__. Refs #19816. # ManyToManyDescriptor.__set__. Refs #19816.
self.a1.publications = [self.p1, self.p2] self.a1.publications = [self.p1, self.p2]
qs = self.a1.publications.filter(title='The Python Journal') qs = self.a1.publications.filter(title='The Python Journal')
...@@ -424,7 +424,7 @@ class ManyToManyTests(TestCase): ...@@ -424,7 +424,7 @@ class ManyToManyTests(TestCase):
def test_reverse_assign_with_queryset(self): def test_reverse_assign_with_queryset(self):
# Ensure that querysets used in M2M assignments are pre-evaluated # Ensure that querysets used in M2M assignments are pre-evaluated
# so their value isn't affected by the clearing operation in # so their value isn't affected by the clearing operation in
# ManyRelatedObjectsDescriptor.__set__. Refs #19816. # ManyToManyDescriptor.__set__. Refs #19816.
self.p1.article_set = [self.a1, self.a2] self.p1.article_set = [self.a1, self.a2]
qs = self.p1.article_set.filter(headline='Django lets you build Web apps easily') qs = self.p1.article_set.filter(headline='Django lets you build Web apps easily')
......
...@@ -106,7 +106,7 @@ class ManyToOneNullTests(TestCase): ...@@ -106,7 +106,7 @@ class ManyToOneNullTests(TestCase):
def test_assign_with_queryset(self): def test_assign_with_queryset(self):
# Ensure that querysets used in reverse FK assignments are pre-evaluated # Ensure that querysets used in reverse FK assignments are pre-evaluated
# so their value isn't affected by the clearing operation in # so their value isn't affected by the clearing operation in
# ForeignRelatedObjectsDescriptor.__set__. Refs #19816. # ReverseManyToOneDescriptor.__set__. Refs #19816.
self.r2.article_set = [self.a2, self.a3] self.r2.article_set = [self.a2, self.a3]
qs = self.r2.article_set.filter(headline="Second") qs = self.r2.article_set.filter(headline="Second")
......
...@@ -595,7 +595,7 @@ class CustomPrefetchTests(TestCase): ...@@ -595,7 +595,7 @@ class CustomPrefetchTests(TestCase):
self.assertEqual(lst2[0].houses_lst[0].rooms_lst[0].main_room_of, self.house1) self.assertEqual(lst2[0].houses_lst[0].rooms_lst[0].main_room_of, self.house1)
self.assertEqual(len(lst2[1].houses_lst), 0) self.assertEqual(len(lst2[1].houses_lst), 0)
# Test ReverseSingleRelatedObjectDescriptor. # Test ForwardManyToOneDescriptor.
houses = House.objects.select_related('owner') houses = House.objects.select_related('owner')
with self.assertNumQueries(6): with self.assertNumQueries(6):
rooms = Room.objects.all().prefetch_related('house') rooms = Room.objects.all().prefetch_related('house')
...@@ -624,7 +624,7 @@ class CustomPrefetchTests(TestCase): ...@@ -624,7 +624,7 @@ class CustomPrefetchTests(TestCase):
with self.assertNumQueries(3): with self.assertNumQueries(3):
getattr(rooms.first().house, 'address') getattr(rooms.first().house, 'address')
# Test SingleRelatedObjectDescriptor. # Test ReverseOneToOneDescriptor.
houses = House.objects.select_related('owner') houses = House.objects.select_related('owner')
with self.assertNumQueries(6): with self.assertNumQueries(6):
rooms = Room.objects.all().prefetch_related('main_room_of') rooms = Room.objects.all().prefetch_related('main_room_of')
......
from django.db import models from django.db import models
from django.db.models.fields.related import ( from django.db.models.fields.related import (
RECURSIVE_RELATIONSHIP_CONSTANT, ManyRelatedObjectsDescriptor, RECURSIVE_RELATIONSHIP_CONSTANT, ManyToManyDescriptor,
ManyToManyField, ManyToManyRel, RelatedField, ManyToManyField, ManyToManyRel, RelatedField,
create_many_to_many_intermediary_model, create_many_to_many_intermediary_model,
) )
...@@ -42,7 +42,7 @@ class CustomManyToManyField(RelatedField): ...@@ -42,7 +42,7 @@ class CustomManyToManyField(RelatedField):
super(CustomManyToManyField, self).contribute_to_class(cls, name, **kwargs) super(CustomManyToManyField, self).contribute_to_class(cls, name, **kwargs)
if not self.remote_field.through and not cls._meta.abstract and not cls._meta.swapped: if not self.remote_field.through and not cls._meta.abstract and not cls._meta.swapped:
self.remote_field.through = create_many_to_many_intermediary_model(self, cls) self.remote_field.through = create_many_to_many_intermediary_model(self, cls)
setattr(cls, self.name, ManyRelatedObjectsDescriptor(self.remote_field)) setattr(cls, self.name, ManyToManyDescriptor(self.remote_field))
self.m2m_db_table = curry(self._get_m2m_db_table, cls._meta) self.m2m_db_table = curry(self._get_m2m_db_table, cls._meta)
def get_internal_type(self): def get_internal_type(self):
......
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