Commit e2296e7f authored by Tim Graham's avatar Tim Graham
Browse files

Fixed #26667 -- Fixed a regression in queries on a OneToOneField that has...

Fixed #26667 -- Fixed a regression in queries on a OneToOneField that has to_field and primary_key=True.

Thanks Simon Charette for review.
parent 54febdb8
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -24,15 +24,16 @@ def get_normalized_value(value, lhs):
    from django.db.models import Model
    if isinstance(value, Model):
        value_list = []
        # A case like Restaurant.objects.filter(place=restaurant_instance),
        # where place is a OneToOneField and the primary key of Restaurant.
        if getattr(lhs.output_field, 'primary_key', False):
            return (value.pk,)
        sources = lhs.output_field.get_path_info()[-1].target_fields
        for source in sources:
            while not isinstance(value, source.model) and source.remote_field:
                source = source.remote_field.model._meta.get_field(source.remote_field.field_name)
            try:
                value_list.append(getattr(value, source.attname))
            except AttributeError:
                # A case like Restaurant.objects.filter(place=restaurant_instance),
                # where place is a OneToOneField and the primary key of Restaurant.
                return (value.pk,)
        return tuple(value_list)
    if not isinstance(value, tuple):
        return (value,)
+3 −0
Original line number Diff line number Diff line
@@ -26,3 +26,6 @@ Bugfixes

* Fixed ``dbshell`` crash on PostgreSQL with an empty database name
  (:ticket:`26698`).

* Fixed a regression in queries on a ``OneToOneField`` that has ``to_field``
  and ``primary_key=True`` (:ticket:`26667`).
+5 −1
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ class MultiModel(models.Model):


class Target(models.Model):
    name = models.CharField(max_length=50)
    name = models.CharField(max_length=50, unique=True)


class Pointer(models.Model):
@@ -98,6 +98,10 @@ class HiddenPointer(models.Model):
    target = models.OneToOneField(Target, models.CASCADE, related_name='hidden+')


class ToFieldPointer(models.Model):
    target = models.OneToOneField(Target, models.CASCADE, to_field='name', primary_key=True)


# Test related objects visibility.
class SchoolManager(models.Manager):
    def get_queryset(self):
+8 −2
Original line number Diff line number Diff line
@@ -6,8 +6,8 @@ from django.utils.deprecation import RemovedInDjango20Warning

from .models import (
    Bar, Director, Favorites, HiddenPointer, ManualPrimaryKey, MultiModel,
    Place, Pointer, RelatedModel, Restaurant, School, Target, UndergroundBar,
    Waiter,
    Place, Pointer, RelatedModel, Restaurant, School, Target, ToFieldPointer,
    UndergroundBar, Waiter,
)


@@ -530,3 +530,9 @@ class OneToOneTests(TestCase):
        r = Restaurant.objects.first()
        r2 = Restaurant.objects.filter(pk__exact=r).first()
        self.assertEqual(r, r2)

    def test_primary_key_to_field_filter(self):
        target = Target.objects.create(name='foo')
        pointer = ToFieldPointer.objects.create(target=target)
        self.assertQuerysetEqual(ToFieldPointer.objects.filter(target=target), [pointer], lambda x: x)
        self.assertQuerysetEqual(ToFieldPointer.objects.filter(pk__exact=pointer), [pointer], lambda x: x)