From 7f8a924b45906a66aa3f562489550eacf2a622ed Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Mon, 3 Apr 2017 13:39:57 +0100 Subject: [PATCH] Refs #27834 -- Removed Value wrapping from StrIndex's substring param. --- django/db/models/functions/base.py | 11 ++++------- docs/ref/models/database-functions.txt | 15 +++++++++------ tests/db_functions/test_strindex.py | 17 +++++++++-------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/django/db/models/functions/base.py b/django/db/models/functions/base.py index 6d08c939e1..7fd396d609 100644 --- a/django/db/models/functions/base.py +++ b/django/db/models/functions/base.py @@ -196,15 +196,12 @@ class StrIndex(Func): function = 'INSTR' arity = 2 - def __init__(self, expression, substring, **extra): + def __init__(self, string, substring, **extra): """ - expression: the name of a field, or an expression returning a string - substring: a string to find inside expression + string: the name of a field, or an expression returning a string + substring: the name of a field, or an expression returning a string """ - if not hasattr(substring, 'resolve_expression'): - substring = Value(substring) - expressions = [expression, substring] - super().__init__(*expressions, output_field=fields.IntegerField(), **extra) + super().__init__(string, substring, output_field=fields.IntegerField(), **extra) def as_postgresql(self, compiler, connection): return super().as_sql(compiler, connection, function='STRPOS') diff --git a/docs/ref/models/database-functions.txt b/docs/ref/models/database-functions.txt index 21b6f897ac..53f70ef242 100644 --- a/docs/ref/models/database-functions.txt +++ b/docs/ref/models/database-functions.txt @@ -240,26 +240,29 @@ Usage example:: ``StrIndex`` ============ -.. class:: StrIndex(expression, substring, **extra) +.. class:: StrIndex(string, substring, **extra) .. versionadded:: 2.0 -Returns a positive integer corresponding to the 1-indexed position of the -first occurrence of ``substring`` inside another string, or 0 if the substring -is not found. +Returns a positive integer corresponding to the 1-indexed position of the first +occurrence of ``substring`` inside ``string``, or 0 if ``substring`` is not +found. Usage example:: + >>> from django.db.models import Value as V >>> from django.db.models.functions import StrIndex >>> Author.objects.create(name='Margaret Smith') >>> Author.objects.create(name='Smith, Margaret') >>> Author.objects.create(name='Margaret Jackson') >>> authors = Author.objects.annotate( - ... smith_index=StrIndex('name', 'Smith')).order_by('smith_index') + ... smith_index=StrIndex('name', V('Smith')) + ... ).order_by('smith_index') >>> authors.first().smith_index 0 >>> authors = Author.objects.annotate( - ... smith_index=StrIndex('name', 'Smith')).filter(smith_index__gt=0) + ... smith_index=StrIndex('name', V('Smith')) + ... ).filter(smith_index__gt=0) , ]> .. warning:: diff --git a/tests/db_functions/test_strindex.py b/tests/db_functions/test_strindex.py index c516d2d2ab..32a153bcbc 100644 --- a/tests/db_functions/test_strindex.py +++ b/tests/db_functions/test_strindex.py @@ -1,3 +1,4 @@ +from django.db.models import Value from django.db.models.functions import StrIndex from django.test import TestCase from django.utils import timezone @@ -10,13 +11,13 @@ class StrIndexTests(TestCase): Author.objects.create(name='George. R. R. Martin') Author.objects.create(name='J. R. R. Tolkien') Author.objects.create(name='Terry Pratchett') - authors = Author.objects.annotate(fullstop=StrIndex('name', 'R.')) + authors = Author.objects.annotate(fullstop=StrIndex('name', Value('R.'))) self.assertQuerysetEqual(authors.order_by('name'), [9, 4, 0], lambda a: a.fullstop) def test_annotate_textfield(self): Article.objects.create( title='How to Django', - text='Lorem ipsum dolor sit amet.', + text='This is about How to Django.', written=timezone.now(), ) Article.objects.create( @@ -24,15 +25,15 @@ class StrIndexTests(TestCase): text="Won't find anything here.", written=timezone.now(), ) - articles = Article.objects.annotate(ipsum_index=StrIndex('text', 'ipsum')) - self.assertQuerysetEqual(articles.order_by('title'), [7, 0], lambda a: a.ipsum_index) + articles = Article.objects.annotate(title_pos=StrIndex('text', 'title')) + self.assertQuerysetEqual(articles.order_by('title'), [15, 0], lambda a: a.title_pos) def test_order_by(self): Author.objects.create(name='Terry Pratchett') Author.objects.create(name='J. R. R. Tolkien') Author.objects.create(name='George. R. R. Martin') self.assertQuerysetEqual( - Author.objects.order_by(StrIndex('name', 'R.').asc()), [ + Author.objects.order_by(StrIndex('name', Value('R.')).asc()), [ 'Terry Pratchett', 'J. R. R. Tolkien', 'George. R. R. Martin', @@ -40,7 +41,7 @@ class StrIndexTests(TestCase): lambda a: a.name ) self.assertQuerysetEqual( - Author.objects.order_by(StrIndex('name', 'R.').desc()), [ + Author.objects.order_by(StrIndex('name', Value('R.')).desc()), [ 'George. R. R. Martin', 'J. R. R. Tolkien', 'Terry Pratchett', @@ -52,14 +53,14 @@ class StrIndexTests(TestCase): Author.objects.create(name='ツリー') Author.objects.create(name='皇帝') Author.objects.create(name='皇帝 ツリー') - authors = Author.objects.annotate(sb=StrIndex('name', 'リ')) + authors = Author.objects.annotate(sb=StrIndex('name', Value('リ'))) self.assertQuerysetEqual(authors.order_by('name'), [2, 0, 5], lambda a: a.sb) def test_filtering(self): Author.objects.create(name='George. R. R. Martin') Author.objects.create(name='Terry Pratchett') self.assertQuerysetEqual( - Author.objects.annotate(middle_name=StrIndex('name', 'R.')).filter(middle_name__gt=0), + Author.objects.annotate(middle_name=StrIndex('name', Value('R.'))).filter(middle_name__gt=0), ['George. R. R. Martin'], lambda a: a.name )