Skip to content

Commit 5c8b7cb

Browse files
committed
Rewrote ExpressionOperatorTests to use annotate() rather than update()
MongoDB doesn't support QuerySet.update() with expressions. Also fixed Number.__str__() on null values (patch submitted upstream).
1 parent 7f8bb59 commit 5c8b7cb

File tree

2 files changed

+86
-101
lines changed

2 files changed

+86
-101
lines changed

tests/expressions/models.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ class Number(models.Model):
5656
decimal_value = models.DecimalField(max_digits=20, decimal_places=17, null=True)
5757

5858
def __str__(self):
59-
return "%i, %.3f, %.17f" % (self.integer, self.float, self.decimal_value)
59+
return "%i, %s, %s" % (
60+
self.integer,
61+
"%.3f" % self.float if self.float is not None else None,
62+
"%.17f" % self.decimal_value if self.decimal_value is not None else None,
63+
)
6064

6165

6266
class Experiment(models.Model):

tests/expressions/tests.py

Lines changed: 81 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,10 +1324,9 @@ class TestModel(Model):
13241324
class ExpressionsNumericTests(TestCase):
13251325
@classmethod
13261326
def setUpTestData(cls):
1327-
Number(integer=-1).save()
1328-
Number(integer=42).save()
1329-
Number(integer=1337).save()
1330-
Number.objects.update(float=F("integer"))
1327+
Number(integer=-1, float=-1).save()
1328+
Number(integer=42, float=42).save()
1329+
Number(integer=1337, float=1337).save()
13311330

13321331
def test_fill_with_value_from_same_object(self):
13331332
"""
@@ -1360,9 +1359,8 @@ def test_filter_not_equals_other_field(self):
13601359
We can filter for objects, where a value is not equals the value
13611360
of an other field.
13621361
"""
1363-
self.assertEqual(
1364-
Number.objects.filter(integer__gt=0).update(integer=F("integer") + 1), 2
1365-
)
1362+
Number.objects.filter(integer=42).update(integer=43)
1363+
Number.objects.filter(integer=1337).update(integer=1338)
13661364
self.assertQuerySetEqual(
13671365
Number.objects.exclude(float=F("integer")),
13681366
[(43, 42), (1338, 1337)],
@@ -1382,15 +1380,12 @@ def test_complex_expressions(self):
13821380
Complex expressions of different connection types are possible.
13831381
"""
13841382
n = Number.objects.create(integer=10, float=123.45)
1385-
self.assertEqual(
1386-
Number.objects.filter(pk=n.pk).update(float=F("integer") + F("float") * 2),
1387-
1,
1383+
qs = Number.objects.filter(pk=n.pk).annotate(
1384+
float1=F("integer") + F("float") * 2
13881385
)
13891386

1390-
self.assertEqual(Number.objects.get(pk=n.pk).integer, 10)
1391-
self.assertEqual(
1392-
Number.objects.get(pk=n.pk).float, Approximate(256.900, places=3)
1393-
)
1387+
self.assertEqual(qs.get(pk=n.pk).integer, 10)
1388+
self.assertEqual(qs.get(pk=n.pk).float1, Approximate(256.900, places=3))
13941389

13951390
def test_decimal_expression(self):
13961391
n = Number.objects.create(integer=1, decimal_value=Decimal("0.5"))
@@ -1408,52 +1403,44 @@ def setUpTestData(cls):
14081403

14091404
def test_lefthand_addition(self):
14101405
# LH Addition of floats and integers
1411-
Number.objects.filter(pk=self.n.pk).update(
1412-
integer=F("integer") + 15, float=F("float") + 42.7
1406+
qs = Number.objects.filter(pk=self.n.pk).annotate(
1407+
integer1=F("integer") + 15, float1=F("float") + 42.7
14131408
)
14141409

1415-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 57)
1416-
self.assertEqual(
1417-
Number.objects.get(pk=self.n.pk).float, Approximate(58.200, places=3)
1418-
)
1410+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 57)
1411+
self.assertEqual(qs.get(pk=self.n.pk).float1, Approximate(58.200, places=3))
14191412

14201413
def test_lefthand_subtraction(self):
14211414
# LH Subtraction of floats and integers
1422-
Number.objects.filter(pk=self.n.pk).update(
1423-
integer=F("integer") - 15, float=F("float") - 42.7
1415+
qs = Number.objects.filter(pk=self.n.pk).annotate(
1416+
integer1=F("integer") - 15, float1=F("float") - 42.7
14241417
)
14251418

1426-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 27)
1427-
self.assertEqual(
1428-
Number.objects.get(pk=self.n.pk).float, Approximate(-27.200, places=3)
1429-
)
1419+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 27)
1420+
self.assertEqual(qs.get(pk=self.n.pk).float1, Approximate(-27.200, places=3))
14301421

14311422
def test_lefthand_multiplication(self):
14321423
# Multiplication of floats and integers
1433-
Number.objects.filter(pk=self.n.pk).update(
1434-
integer=F("integer") * 15, float=F("float") * 42.7
1424+
qs = Number.objects.filter(pk=self.n.pk).annotate(
1425+
integer1=F("integer") * 15, float1=F("float") * 42.7
14351426
)
14361427

1437-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 630)
1438-
self.assertEqual(
1439-
Number.objects.get(pk=self.n.pk).float, Approximate(661.850, places=3)
1440-
)
1428+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 630)
1429+
self.assertEqual(qs.get(pk=self.n.pk).float1, Approximate(661.850, places=3))
14411430

14421431
def test_lefthand_division(self):
14431432
# LH Division of floats and integers
1444-
Number.objects.filter(pk=self.n.pk).update(
1445-
integer=F("integer") / 2, float=F("float") / 42.7
1433+
qs = Number.objects.filter(pk=self.n.pk).annotate(
1434+
integer1=F("integer") / 2, float1=F("float") / 42.7
14461435
)
14471436

1448-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 21)
1449-
self.assertEqual(
1450-
Number.objects.get(pk=self.n.pk).float, Approximate(0.363, places=3)
1451-
)
1437+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 21)
1438+
self.assertEqual(qs.get(pk=self.n.pk).float1, Approximate(0.363, places=3))
14521439

14531440
def test_lefthand_modulo(self):
14541441
# LH Modulo arithmetic on integers
1455-
Number.objects.filter(pk=self.n.pk).update(integer=F("integer") % 20)
1456-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 2)
1442+
qs = Number.objects.filter(pk=self.n.pk).annotate(integer1=F("integer") % 20)
1443+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 2)
14571444

14581445
def test_lefthand_modulo_null(self):
14591446
# LH Modulo arithmetic on integers.
@@ -1463,28 +1450,32 @@ def test_lefthand_modulo_null(self):
14631450

14641451
def test_lefthand_bitwise_and(self):
14651452
# LH Bitwise ands on integers
1466-
Number.objects.filter(pk=self.n.pk).update(integer=F("integer").bitand(56))
1467-
Number.objects.filter(pk=self.n1.pk).update(integer=F("integer").bitand(-56))
1453+
qs1 = Number.objects.filter(pk=self.n.pk).annotate(
1454+
integer1=F("integer").bitand(56)
1455+
)
1456+
qs2 = Number.objects.filter(pk=self.n1.pk).annotate(
1457+
integer1=F("integer").bitand(-56)
1458+
)
14681459

1469-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 40)
1470-
self.assertEqual(Number.objects.get(pk=self.n1.pk).integer, -64)
1460+
self.assertEqual(qs1.get(pk=self.n.pk).integer1, 40)
1461+
self.assertEqual(qs2.get(pk=self.n1.pk).integer1, -64)
14711462

14721463
def test_lefthand_bitwise_left_shift_operator(self):
1473-
Number.objects.update(integer=F("integer").bitleftshift(2))
1474-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 168)
1475-
self.assertEqual(Number.objects.get(pk=self.n1.pk).integer, -168)
1464+
qs = Number.objects.annotate(integer1=F("integer").bitleftshift(2))
1465+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 168)
1466+
self.assertEqual(qs.get(pk=self.n1.pk).integer1, -168)
14761467

14771468
def test_lefthand_bitwise_right_shift_operator(self):
1478-
Number.objects.update(integer=F("integer").bitrightshift(2))
1479-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 10)
1480-
self.assertEqual(Number.objects.get(pk=self.n1.pk).integer, -11)
1469+
qs = Number.objects.annotate(integer1=F("integer").bitrightshift(2))
1470+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 10)
1471+
self.assertEqual(qs.get(pk=self.n1.pk).integer1, -11)
14811472

14821473
def test_lefthand_bitwise_or(self):
14831474
# LH Bitwise or on integers
1484-
Number.objects.update(integer=F("integer").bitor(48))
1475+
qs = Number.objects.annotate(integer1=F("integer").bitor(48))
14851476

1486-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 58)
1487-
self.assertEqual(Number.objects.get(pk=self.n1.pk).integer, -10)
1477+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 58)
1478+
self.assertEqual(qs.get(pk=self.n1.pk).integer1, -10)
14881479

14891480
def test_lefthand_transformed_field_bitwise_or(self):
14901481
Employee.objects.create(firstname="Max", lastname="Mustermann")
@@ -1494,30 +1485,30 @@ def test_lefthand_transformed_field_bitwise_or(self):
14941485

14951486
def test_lefthand_power(self):
14961487
# LH Power arithmetic operation on floats and integers
1497-
Number.objects.filter(pk=self.n.pk).update(
1498-
integer=F("integer") ** 2, float=F("float") ** 1.5
1499-
)
1500-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 1764)
1501-
self.assertEqual(
1502-
Number.objects.get(pk=self.n.pk).float, Approximate(61.02, places=2)
1488+
qs = Number.objects.filter(pk=self.n.pk).annotate(
1489+
integer1=F("integer") ** 2, float1=F("float") ** 1.5
15031490
)
1491+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 1764)
1492+
self.assertEqual(qs.get(pk=self.n.pk).float1, Approximate(61.02, places=2))
15041493

15051494
def test_lefthand_bitwise_xor(self):
1506-
Number.objects.update(integer=F("integer").bitxor(48))
1507-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 26)
1508-
self.assertEqual(Number.objects.get(pk=self.n1.pk).integer, -26)
1495+
qs = Number.objects.annotate(integer1=F("integer").bitxor(48))
1496+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 26)
1497+
self.assertEqual(qs.get(pk=self.n1.pk).integer1, -26)
15091498

15101499
def test_lefthand_bitwise_xor_null(self):
15111500
employee = Employee.objects.create(firstname="John", lastname="Doe")
1512-
Employee.objects.update(salary=F("salary").bitxor(48))
1513-
employee.refresh_from_db()
1514-
self.assertIsNone(employee.salary)
1501+
qs = Employee.objects.annotate(salary1=F("salary").bitxor(48))
1502+
self.assertIsNone(qs.get(id=employee.id).salary1)
15151503

15161504
def test_lefthand_bitwise_xor_right_null(self):
15171505
employee = Employee.objects.create(firstname="John", lastname="Doe", salary=48)
1518-
Employee.objects.update(salary=F("salary").bitxor(None))
1519-
employee.refresh_from_db()
1520-
self.assertIsNone(employee.salary)
1506+
qs = Employee.objects.annotate(
1507+
salary1=ExpressionWrapper(
1508+
F("salary").bitxor(None), output_field=IntegerField()
1509+
)
1510+
)
1511+
self.assertIsNone(qs.get(id=employee.id).salary1)
15211512

15221513
@unittest.skipUnless(
15231514
connection.vendor == "oracle", "Oracle doesn't support bitwise XOR."
@@ -1529,64 +1520,54 @@ def test_lefthand_bitwise_xor_not_supported(self):
15291520

15301521
def test_right_hand_addition(self):
15311522
# Right hand operators
1532-
Number.objects.filter(pk=self.n.pk).update(
1533-
integer=15 + F("integer"), float=42.7 + F("float")
1523+
qs = Number.objects.filter(pk=self.n.pk).annotate(
1524+
integer1=15 + F("integer"), float1=42.7 + F("float")
15341525
)
15351526

15361527
# RH Addition of floats and integers
1537-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 57)
1538-
self.assertEqual(
1539-
Number.objects.get(pk=self.n.pk).float, Approximate(58.200, places=3)
1540-
)
1528+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 57)
1529+
self.assertEqual(qs.get(pk=self.n.pk).float1, Approximate(58.200, places=3))
15411530

15421531
def test_right_hand_subtraction(self):
1543-
Number.objects.filter(pk=self.n.pk).update(
1544-
integer=15 - F("integer"), float=42.7 - F("float")
1532+
qs = Number.objects.filter(pk=self.n.pk).annotate(
1533+
integer1=15 - F("integer"), float1=42.7 - F("float")
15451534
)
15461535

15471536
# RH Subtraction of floats and integers
1548-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, -27)
1549-
self.assertEqual(
1550-
Number.objects.get(pk=self.n.pk).float, Approximate(27.200, places=3)
1551-
)
1537+
self.assertEqual(qs.get(pk=self.n.pk).integer1, -27)
1538+
self.assertEqual(qs.get(pk=self.n.pk).float1, Approximate(27.200, places=3))
15521539

15531540
def test_right_hand_multiplication(self):
15541541
# RH Multiplication of floats and integers
1555-
Number.objects.filter(pk=self.n.pk).update(
1556-
integer=15 * F("integer"), float=42.7 * F("float")
1542+
qs = Number.objects.filter(pk=self.n.pk).annotate(
1543+
integer1=15 * F("integer"), float1=42.7 * F("float")
15571544
)
15581545

1559-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 630)
1560-
self.assertEqual(
1561-
Number.objects.get(pk=self.n.pk).float, Approximate(661.850, places=3)
1562-
)
1546+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 630)
1547+
self.assertEqual(qs.get(pk=self.n.pk).float1, Approximate(661.850, places=3))
15631548

15641549
def test_right_hand_division(self):
15651550
# RH Division of floats and integers
1566-
Number.objects.filter(pk=self.n.pk).update(
1567-
integer=640 / F("integer"), float=42.7 / F("float")
1551+
qs = Number.objects.filter(pk=self.n.pk).annotate(
1552+
integer1=640 / F("integer"), float1=42.7 / F("float")
15681553
)
15691554

1570-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 15)
1571-
self.assertEqual(
1572-
Number.objects.get(pk=self.n.pk).float, Approximate(2.755, places=3)
1573-
)
1555+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 15)
1556+
self.assertEqual(qs.get(pk=self.n.pk).float1, Approximate(2.755, places=3))
15741557

15751558
def test_right_hand_modulo(self):
15761559
# RH Modulo arithmetic on integers
1577-
Number.objects.filter(pk=self.n.pk).update(integer=69 % F("integer"))
1560+
qs = Number.objects.filter(pk=self.n.pk).annotate(integer1=69 % F("integer"))
15781561

1579-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 27)
1562+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 27)
15801563

15811564
def test_righthand_power(self):
15821565
# RH Power arithmetic operation on floats and integers
1583-
Number.objects.filter(pk=self.n.pk).update(
1584-
integer=2 ** F("integer"), float=1.5 ** F("float")
1585-
)
1586-
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 4398046511104)
1587-
self.assertEqual(
1588-
Number.objects.get(pk=self.n.pk).float, Approximate(536.308, places=3)
1566+
qs = Number.objects.filter(pk=self.n.pk).annotate(
1567+
integer1=2 ** F("integer"), float1=1.5 ** F("float")
15891568
)
1569+
self.assertEqual(qs.get(pk=self.n.pk).integer1, 4398046511104)
1570+
self.assertEqual(qs.get(pk=self.n.pk).float1, Approximate(536.308, places=3))
15901571

15911572

15921573
class FTimeDeltaTests(TestCase):

0 commit comments

Comments
 (0)