mirror of
				https://github.com/django/django.git
				synced 2025-10-30 17:16:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			82 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from unittest import skipUnless
 | |
| 
 | |
| from django.db import connection
 | |
| from django.db.models import CharField, TextField, Value as V
 | |
| from django.db.models.functions import Concat, ConcatPair, Upper
 | |
| from django.test import TestCase
 | |
| from django.utils import timezone
 | |
| 
 | |
| from ..models import Article, Author
 | |
| 
 | |
| lorem_ipsum = """
 | |
|     Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
 | |
|     tempor incididunt ut labore et dolore magna aliqua."""
 | |
| 
 | |
| 
 | |
| class ConcatTests(TestCase):
 | |
| 
 | |
|     def test_basic(self):
 | |
|         Author.objects.create(name='Jayden')
 | |
|         Author.objects.create(name='John Smith', alias='smithj', goes_by='John')
 | |
|         Author.objects.create(name='Margaret', goes_by='Maggie')
 | |
|         Author.objects.create(name='Rhonda', alias='adnohR')
 | |
|         authors = Author.objects.annotate(joined=Concat('alias', 'goes_by'))
 | |
|         self.assertQuerysetEqual(
 | |
|             authors.order_by('name'), [
 | |
|                 '',
 | |
|                 'smithjJohn',
 | |
|                 'Maggie',
 | |
|                 'adnohR',
 | |
|             ],
 | |
|             lambda a: a.joined
 | |
|         )
 | |
| 
 | |
|     def test_gt_two_expressions(self):
 | |
|         with self.assertRaisesMessage(ValueError, 'Concat must take at least two expressions'):
 | |
|             Author.objects.annotate(joined=Concat('alias'))
 | |
| 
 | |
|     def test_many(self):
 | |
|         Author.objects.create(name='Jayden')
 | |
|         Author.objects.create(name='John Smith', alias='smithj', goes_by='John')
 | |
|         Author.objects.create(name='Margaret', goes_by='Maggie')
 | |
|         Author.objects.create(name='Rhonda', alias='adnohR')
 | |
|         authors = Author.objects.annotate(
 | |
|             joined=Concat('name', V(' ('), 'goes_by', V(')'), output_field=CharField()),
 | |
|         )
 | |
|         self.assertQuerysetEqual(
 | |
|             authors.order_by('name'), [
 | |
|                 'Jayden ()',
 | |
|                 'John Smith (John)',
 | |
|                 'Margaret (Maggie)',
 | |
|                 'Rhonda ()',
 | |
|             ],
 | |
|             lambda a: a.joined
 | |
|         )
 | |
| 
 | |
|     def test_mixed_char_text(self):
 | |
|         Article.objects.create(title='The Title', text=lorem_ipsum, written=timezone.now())
 | |
|         article = Article.objects.annotate(
 | |
|             title_text=Concat('title', V(' - '), 'text', output_field=TextField()),
 | |
|         ).get(title='The Title')
 | |
|         self.assertEqual(article.title + ' - ' + article.text, article.title_text)
 | |
|         # Wrap the concat in something else to ensure that text is returned
 | |
|         # rather than bytes.
 | |
|         article = Article.objects.annotate(
 | |
|             title_text=Upper(Concat('title', V(' - '), 'text', output_field=TextField())),
 | |
|         ).get(title='The Title')
 | |
|         expected = article.title + ' - ' + article.text
 | |
|         self.assertEqual(expected.upper(), article.title_text)
 | |
| 
 | |
|     @skipUnless(connection.vendor == 'sqlite', "sqlite specific implementation detail.")
 | |
|     def test_coalesce_idempotent(self):
 | |
|         pair = ConcatPair(V('a'), V('b'))
 | |
|         # Check nodes counts
 | |
|         self.assertEqual(len(list(pair.flatten())), 3)
 | |
|         self.assertEqual(len(list(pair.coalesce().flatten())), 7)  # + 2 Coalesce + 2 Value()
 | |
|         self.assertEqual(len(list(pair.flatten())), 3)
 | |
| 
 | |
|     def test_sql_generation_idempotency(self):
 | |
|         qs = Article.objects.annotate(description=Concat('title', V(': '), 'summary'))
 | |
|         # Multiple compilations should not alter the generated query.
 | |
|         self.assertEqual(str(qs.query), str(qs.all().query))
 |