Browse Source

Fixed #26285 -- Deprecated the MySQL-specific __search lookup.

Marc Tamlyn 9 years ago
parent
commit
8ddc79a799

+ 1 - 0
django/db/backends/base/operations.py

@@ -191,6 +191,7 @@ class BaseDatabaseOperations(object):
         search of the given field_name. Note that the resulting string should
         contain a '%s' placeholder for the value being searched against.
         """
+        # RemovedInDjango20Warning
         raise NotImplementedError('Full-text search is not implemented for this database backend')
 
     def last_executed_query(self, cursor, sql, params):

+ 1 - 0
django/db/backends/mysql/operations.py

@@ -91,6 +91,7 @@ class DatabaseOperations(BaseDatabaseOperations):
         return [(None, ("NULL", [], False))]
 
     def fulltext_search_sql(self, field_name):
+        # RemovedInDjango20Warning
         return 'MATCH (%s) AGAINST (%%s IN BOOLEAN MODE)' % field_name
 
     def last_executed_query(self, cursor, sql, params):

+ 6 - 0
django/db/models/lookups.py

@@ -1,3 +1,4 @@
+import warnings
 from copy import copy
 
 from django.conf import settings
@@ -7,6 +8,7 @@ from django.db.models.fields import (
 )
 from django.db.models.query_utils import RegisterLookupMixin
 from django.utils import timezone
+from django.utils.deprecation import RemovedInDjango20Warning
 from django.utils.functional import cached_property
 from django.utils.six.moves import range
 
@@ -373,6 +375,10 @@ class Search(BuiltinLookup):
     lookup_name = 'search'
 
     def as_sql(self, compiler, connection):
+        warnings.warn(
+            'The `__search` lookup is deprecated. See the 1.10 release notes '
+            'for how to replace it.', RemovedInDjango20Warning, stacklevel=2
+        )
         lhs, lhs_params = self.process_lhs(compiler, connection)
         rhs, rhs_params = self.process_rhs(compiler, connection)
         sql_template = connection.ops.fulltext_search_sql(field_name=lhs)

+ 3 - 0
docs/internals/deprecation.txt

@@ -141,6 +141,9 @@ details on these changes.
 * Support for query lookups using the model name when
   ``Meta.default_related_name`` is set will be removed.
 
+* The ``__search`` query lookup and the
+  ``DatabaseOperations.fulltext_search_sql()`` method will be removed.
+
 .. _deprecation-removed-in-1.10:
 
 1.10

+ 2 - 9
docs/ref/models/fields.txt

@@ -1847,15 +1847,8 @@ Field API reference
     .. method:: get_prep_lookup(lookup_type, value)
 
         Prepares ``value`` to the database prior to be used in a lookup.
-        The ``lookup_type`` will be one of the valid Django filter lookups:
-        ``"exact"``, ``"iexact"``, ``"contains"``, ``"icontains"``,
-        ``"gt"``, ``"gte"``, ``"lt"``, ``"lte"``, ``"in"``, ``"startswith"``,
-        ``"istartswith"``, ``"endswith"``, ``"iendswith"``, ``"range"``,
-        ``"year"``, ``"month"``, ``"day"``, ``"isnull"``, ``"search"``,
-        ``"regex"``, and ``"iregex"``.
-
-        If you are using :doc:`Custom lookups </ref/models/lookups>` the
-        ``lookup_type`` can be any ``lookup_name`` registered in the field.
+        The ``lookup_type`` will be the registered name of the lookup. For
+        example: ``"exact"``, ``"iexact"``, or ``"contains"``.
 
         See :ref:`preparing-values-for-use-in-database-lookups` for usage.
 

+ 5 - 0
docs/ref/models/querysets.txt

@@ -2771,6 +2771,11 @@ SQL equivalent::
 ``search``
 ~~~~~~~~~~
 
+.. deprecated:: 1.10
+
+    See :ref:`the 1.10 release notes <search-lookup-replacement>` for how to
+    replace it.
+
 A boolean full-text search, taking advantage of full-text indexing. This is
 like :lookup:`contains` but is significantly faster due to full-text indexing.
 

+ 22 - 0
docs/releases/1.10.txt

@@ -740,6 +740,28 @@ use the default_related_name ``bars``::
 
     >>> Foo.object.get(bars=bar)
 
+.. _search-lookup-replacement:
+
+``__search`` query lookup
+-------------------------
+
+The ``search`` lookup, which supports MySQL only and is extremely limited in
+features, is deprecated. Replace it with a custom lookup::
+
+    from django.db import models
+
+    class Search(models.Lookup):
+        lookup_name = 'search'
+
+        def as_mysql(self, compiler, connection):
+            lhs, lhs_params = self.process_lhs(compiler, connection)
+            rhs, rhs_params = self.process_rhs(compiler, connection)
+            params = lhs_params + rhs_params
+            return 'MATCH (%s) AGAINST (%s IN BOOLEAN MODE)' % (lhs, rhs), params
+
+    models.CharField.register_lookup(Search)
+    models.TextField.register_lookup(Search)
+
 Miscellaneous
 -------------
 

+ 1 - 0
tests/lookup/models.py

@@ -79,6 +79,7 @@ class Player(models.Model):
 # is only available when using MySQL 5.6, or when using MyISAM
 # tables. As 5.6 isn't common yet, lets use MyISAM table for
 # testing. The table is manually created by the test method.
+# RemovedInDjango20Warning
 class MyISAMArticle(models.Model):
     headline = models.CharField(max_length=100)
 

+ 5 - 1
tests/lookup/tests.py

@@ -7,7 +7,10 @@ from unittest import skipUnless
 
 from django.core.exceptions import FieldError
 from django.db import connection
-from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature
+from django.test import (
+    TestCase, TransactionTestCase, ignore_warnings, skipUnlessDBFeature,
+)
+from django.utils.deprecation import RemovedInDjango20Warning
 
 from .models import Article, Author, Game, MyISAMArticle, Player, Season, Tag
 
@@ -792,6 +795,7 @@ class LookupTests(TestCase):
 class LookupTransactionTests(TransactionTestCase):
     available_apps = ['lookup']
 
+    @ignore_warnings(category=RemovedInDjango20Warning)
     @skipUnless(connection.vendor == 'mysql', 'requires MySQL')
     def test_mysql_lookup_search(self):
         # To use fulltext indexes on MySQL either version 5.6 is needed, or one must use