test_coalesce.py 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. from django.db.models import Subquery, TextField
  2. from django.db.models.functions import Coalesce, Lower
  3. from django.test import TestCase
  4. from django.utils import timezone
  5. from ..models import Article, Author
  6. lorem_ipsum = """
  7. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
  8. tempor incididunt ut labore et dolore magna aliqua."""
  9. class CoalesceTests(TestCase):
  10. def test_basic(self):
  11. Author.objects.create(name="John Smith", alias="smithj")
  12. Author.objects.create(name="Rhonda")
  13. authors = Author.objects.annotate(display_name=Coalesce("alias", "name"))
  14. self.assertQuerySetEqual(
  15. authors.order_by("name"), ["smithj", "Rhonda"], lambda a: a.display_name
  16. )
  17. def test_gt_two_expressions(self):
  18. with self.assertRaisesMessage(
  19. ValueError, "Coalesce must take at least two expressions"
  20. ):
  21. Author.objects.annotate(display_name=Coalesce("alias"))
  22. def test_mixed_values(self):
  23. a1 = Author.objects.create(name="John Smith", alias="smithj")
  24. a2 = Author.objects.create(name="Rhonda")
  25. ar1 = Article.objects.create(
  26. title="How to Django",
  27. text=lorem_ipsum,
  28. written=timezone.now(),
  29. )
  30. ar1.authors.add(a1)
  31. ar1.authors.add(a2)
  32. # mixed Text and Char
  33. article = Article.objects.annotate(
  34. headline=Coalesce("summary", "text", output_field=TextField()),
  35. )
  36. self.assertQuerySetEqual(
  37. article.order_by("title"), [lorem_ipsum], lambda a: a.headline
  38. )
  39. # mixed Text and Char wrapped
  40. article = Article.objects.annotate(
  41. headline=Coalesce(
  42. Lower("summary"), Lower("text"), output_field=TextField()
  43. ),
  44. )
  45. self.assertQuerySetEqual(
  46. article.order_by("title"), [lorem_ipsum.lower()], lambda a: a.headline
  47. )
  48. def test_ordering(self):
  49. Author.objects.create(name="John Smith", alias="smithj")
  50. Author.objects.create(name="Rhonda")
  51. authors = Author.objects.order_by(Coalesce("alias", "name"))
  52. self.assertQuerySetEqual(authors, ["Rhonda", "John Smith"], lambda a: a.name)
  53. authors = Author.objects.order_by(Coalesce("alias", "name").asc())
  54. self.assertQuerySetEqual(authors, ["Rhonda", "John Smith"], lambda a: a.name)
  55. authors = Author.objects.order_by(Coalesce("alias", "name").desc())
  56. self.assertQuerySetEqual(authors, ["John Smith", "Rhonda"], lambda a: a.name)
  57. def test_empty_queryset(self):
  58. Author.objects.create(name="John Smith")
  59. queryset = Author.objects.values("id")
  60. tests = [
  61. (queryset.none(), "QuerySet.none()"),
  62. (queryset.filter(id=0), "QuerySet.filter(id=0)"),
  63. (Subquery(queryset.none()), "Subquery(QuerySet.none())"),
  64. (Subquery(queryset.filter(id=0)), "Subquery(Queryset.filter(id=0)"),
  65. ]
  66. for empty_query, description in tests:
  67. with self.subTest(description), self.assertNumQueries(1):
  68. qs = Author.objects.annotate(annotation=Coalesce(empty_query, 42))
  69. self.assertEqual(qs.first().annotation, 42)