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