Refs #27834 -- Removed Value wrapping from StrIndex's substring param.

This commit is contained in:
Adam Johnson 2017-04-03 13:39:57 +01:00 committed by Tim Graham
parent 7170820b4e
commit 7f8a924b45
3 changed files with 22 additions and 21 deletions

View File

@ -196,15 +196,12 @@ class StrIndex(Func):
function = 'INSTR' function = 'INSTR'
arity = 2 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 string: the name of a field, or an expression returning a string
substring: a string to find inside expression substring: the name of a field, or an expression returning a string
""" """
if not hasattr(substring, 'resolve_expression'): super().__init__(string, substring, output_field=fields.IntegerField(), **extra)
substring = Value(substring)
expressions = [expression, substring]
super().__init__(*expressions, output_field=fields.IntegerField(), **extra)
def as_postgresql(self, compiler, connection): def as_postgresql(self, compiler, connection):
return super().as_sql(compiler, connection, function='STRPOS') return super().as_sql(compiler, connection, function='STRPOS')

View File

@ -240,26 +240,29 @@ Usage example::
``StrIndex`` ``StrIndex``
============ ============
.. class:: StrIndex(expression, substring, **extra) .. class:: StrIndex(string, substring, **extra)
.. versionadded:: 2.0 .. versionadded:: 2.0
Returns a positive integer corresponding to the 1-indexed position of the Returns a positive integer corresponding to the 1-indexed position of the first
first occurrence of ``substring`` inside another string, or 0 if the substring occurrence of ``substring`` inside ``string``, or 0 if ``substring`` is not
is not found. found.
Usage example:: Usage example::
>>> from django.db.models import Value as V
>>> from django.db.models.functions import StrIndex >>> from django.db.models.functions import StrIndex
>>> Author.objects.create(name='Margaret Smith') >>> Author.objects.create(name='Margaret Smith')
>>> Author.objects.create(name='Smith, Margaret') >>> Author.objects.create(name='Smith, Margaret')
>>> Author.objects.create(name='Margaret Jackson') >>> Author.objects.create(name='Margaret Jackson')
>>> authors = Author.objects.annotate( >>> 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 >>> authors.first().smith_index
0 0
>>> authors = Author.objects.annotate( >>> 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)
<QuerySet [<Author: Margaret Smith>, <Author: Smith, Margaret>]> <QuerySet [<Author: Margaret Smith>, <Author: Smith, Margaret>]>
.. warning:: .. warning::

View File

@ -1,3 +1,4 @@
from django.db.models import Value
from django.db.models.functions import StrIndex from django.db.models.functions import StrIndex
from django.test import TestCase from django.test import TestCase
from django.utils import timezone from django.utils import timezone
@ -10,13 +11,13 @@ class StrIndexTests(TestCase):
Author.objects.create(name='George. R. R. Martin') Author.objects.create(name='George. R. R. Martin')
Author.objects.create(name='J. R. R. Tolkien') Author.objects.create(name='J. R. R. Tolkien')
Author.objects.create(name='Terry Pratchett') 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) self.assertQuerysetEqual(authors.order_by('name'), [9, 4, 0], lambda a: a.fullstop)
def test_annotate_textfield(self): def test_annotate_textfield(self):
Article.objects.create( Article.objects.create(
title='How to Django', title='How to Django',
text='Lorem ipsum dolor sit amet.', text='This is about How to Django.',
written=timezone.now(), written=timezone.now(),
) )
Article.objects.create( Article.objects.create(
@ -24,15 +25,15 @@ class StrIndexTests(TestCase):
text="Won't find anything here.", text="Won't find anything here.",
written=timezone.now(), written=timezone.now(),
) )
articles = Article.objects.annotate(ipsum_index=StrIndex('text', 'ipsum')) articles = Article.objects.annotate(title_pos=StrIndex('text', 'title'))
self.assertQuerysetEqual(articles.order_by('title'), [7, 0], lambda a: a.ipsum_index) self.assertQuerysetEqual(articles.order_by('title'), [15, 0], lambda a: a.title_pos)
def test_order_by(self): def test_order_by(self):
Author.objects.create(name='Terry Pratchett') Author.objects.create(name='Terry Pratchett')
Author.objects.create(name='J. R. R. Tolkien') Author.objects.create(name='J. R. R. Tolkien')
Author.objects.create(name='George. R. R. Martin') Author.objects.create(name='George. R. R. Martin')
self.assertQuerysetEqual( self.assertQuerysetEqual(
Author.objects.order_by(StrIndex('name', 'R.').asc()), [ Author.objects.order_by(StrIndex('name', Value('R.')).asc()), [
'Terry Pratchett', 'Terry Pratchett',
'J. R. R. Tolkien', 'J. R. R. Tolkien',
'George. R. R. Martin', 'George. R. R. Martin',
@ -40,7 +41,7 @@ class StrIndexTests(TestCase):
lambda a: a.name lambda a: a.name
) )
self.assertQuerysetEqual( self.assertQuerysetEqual(
Author.objects.order_by(StrIndex('name', 'R.').desc()), [ Author.objects.order_by(StrIndex('name', Value('R.')).desc()), [
'George. R. R. Martin', 'George. R. R. Martin',
'J. R. R. Tolkien', 'J. R. R. Tolkien',
'Terry Pratchett', 'Terry Pratchett',
@ -52,14 +53,14 @@ class StrIndexTests(TestCase):
Author.objects.create(name='ツリー') Author.objects.create(name='ツリー')
Author.objects.create(name='皇帝') 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) self.assertQuerysetEqual(authors.order_by('name'), [2, 0, 5], lambda a: a.sb)
def test_filtering(self): def test_filtering(self):
Author.objects.create(name='George. R. R. Martin') Author.objects.create(name='George. R. R. Martin')
Author.objects.create(name='Terry Pratchett') Author.objects.create(name='Terry Pratchett')
self.assertQuerysetEqual( 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'], ['George. R. R. Martin'],
lambda a: a.name lambda a: a.name
) )