mirror of
https://github.com/django/django.git
synced 2025-04-12 11:32:20 +00:00
[2.2.x] Fixed #30628 -- Adjusted expression identity to differentiate bound fields.
Expressions referring to different bound fields should not be considered equal. Thanks Julien Enselme for the detailed report. Regression in bc7e288ca9554ac1a0a19941302dea19df1acd21. Backport of ee6e93ec8727d0f5ed33190a3c354867669ed72f from master
This commit is contained in:
parent
8f0b9e7f9a
commit
9dee8515d6
@ -372,7 +372,10 @@ class BaseExpression:
|
||||
identity = [self.__class__]
|
||||
for arg, value in arguments:
|
||||
if isinstance(value, fields.Field):
|
||||
value = type(value)
|
||||
if value.name and value.model:
|
||||
value = (value.model._meta.label, value.name)
|
||||
else:
|
||||
value = type(value)
|
||||
else:
|
||||
value = make_hashable(value)
|
||||
identity.append((arg, value))
|
||||
|
@ -9,4 +9,6 @@ Django 2.2.4 fixes several bugs in 2.2.3.
|
||||
Bugfixes
|
||||
========
|
||||
|
||||
* ...
|
||||
* Fixed a regression in Django 2.2 when ordering a ``QuerySet.union()``,
|
||||
``intersection()``, or ``difference()`` by a field type present more than
|
||||
once results in the wrong ordering being used (:ticket:`30628`).
|
||||
|
@ -21,7 +21,7 @@ from django.db.models.functions import (
|
||||
from django.db.models.sql import constants
|
||||
from django.db.models.sql.datastructures import Join
|
||||
from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature
|
||||
from django.test.utils import Approximate
|
||||
from django.test.utils import Approximate, isolate_apps
|
||||
|
||||
from .models import (
|
||||
UUID, UUIDPK, Company, Employee, Experiment, Number, RemoteEmployee,
|
||||
@ -839,6 +839,7 @@ class ExpressionsTests(TestCase):
|
||||
)
|
||||
|
||||
|
||||
@isolate_apps('expressions')
|
||||
class SimpleExpressionTests(SimpleTestCase):
|
||||
|
||||
def test_equal(self):
|
||||
@ -852,6 +853,15 @@ class SimpleExpressionTests(SimpleTestCase):
|
||||
Expression(models.CharField())
|
||||
)
|
||||
|
||||
class TestModel(models.Model):
|
||||
field = models.IntegerField()
|
||||
other_field = models.IntegerField()
|
||||
|
||||
self.assertNotEqual(
|
||||
Expression(TestModel._meta.get_field('field')),
|
||||
Expression(TestModel._meta.get_field('other_field')),
|
||||
)
|
||||
|
||||
def test_hash(self):
|
||||
self.assertEqual(hash(Expression()), hash(Expression()))
|
||||
self.assertEqual(
|
||||
@ -863,6 +873,15 @@ class SimpleExpressionTests(SimpleTestCase):
|
||||
hash(Expression(models.CharField())),
|
||||
)
|
||||
|
||||
class TestModel(models.Model):
|
||||
field = models.IntegerField()
|
||||
other_field = models.IntegerField()
|
||||
|
||||
self.assertNotEqual(
|
||||
hash(Expression(TestModel._meta.get_field('field'))),
|
||||
hash(Expression(TestModel._meta.get_field('other_field'))),
|
||||
)
|
||||
|
||||
|
||||
class ExpressionsNumericTests(TestCase):
|
||||
|
||||
|
@ -143,6 +143,7 @@ class Cover(models.Model):
|
||||
|
||||
class Number(models.Model):
|
||||
num = models.IntegerField()
|
||||
other_num = models.IntegerField(null=True)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.num)
|
||||
|
@ -9,7 +9,7 @@ from .models import Number, ReservedName
|
||||
class QuerySetSetOperationTests(TestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
Number.objects.bulk_create(Number(num=i) for i in range(10))
|
||||
Number.objects.bulk_create(Number(num=i, other_num=10 - i) for i in range(10))
|
||||
|
||||
def number_transform(self, value):
|
||||
return value.num
|
||||
@ -225,3 +225,10 @@ class QuerySetSetOperationTests(TestCase):
|
||||
qs1 = Number.objects.all()
|
||||
qs2 = Number.objects.intersection(Number.objects.filter(num__gt=1))
|
||||
self.assertEqual(qs1.difference(qs2).count(), 2)
|
||||
|
||||
def test_order_by_same_type(self):
|
||||
qs = Number.objects.all()
|
||||
union = qs.union(qs)
|
||||
numbers = list(range(10))
|
||||
self.assertNumbersEqual(union.order_by('num'), numbers)
|
||||
self.assertNumbersEqual(union.order_by('other_num'), reversed(numbers))
|
||||
|
@ -2345,7 +2345,7 @@ class ValuesQuerysetTests(TestCase):
|
||||
qs = Number.objects.extra(select={'num2': 'num+1'}).annotate(Count('id'))
|
||||
values = qs.values_list(named=True).first()
|
||||
self.assertEqual(type(values).__name__, 'Row')
|
||||
self.assertEqual(values._fields, ('num2', 'id', 'num', 'id__count'))
|
||||
self.assertEqual(values._fields, ('num2', 'id', 'num', 'other_num', 'id__count'))
|
||||
self.assertEqual(values.num, 72)
|
||||
self.assertEqual(values.num2, 73)
|
||||
self.assertEqual(values.id__count, 1)
|
||||
|
Loading…
x
Reference in New Issue
Block a user