Commits

Anonymous committed a0963d8

Fixed #2559 -- Added cool new operators for Admin.search_fields, plus documentation. Thanks, Andy Dustman.

  • Participants
  • Parent commits 105a672

Comments (0)

Files changed (3)

     deric@monowerks.com
     dne@mayonnaise.net
     Jeremy Dunck <http://dunck.us/>
+    Andy Dustman <farcepest@gmail.com>
     Clint Ecker
     gandalf@owca.info
     Baishampayan Ghose

File django/contrib/admin/views/main.py

         qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field)
 
         # Apply keyword searches.
+        def construct_search(field_name):
+            if field_name.startswith('^'):
+                return "%s__istartswith" % field_name[1:]
+            elif field_name.startswith('='):
+                return "%s__iexact" % field_name[1:]
+            elif field_name.startswith('@'):
+                return "%s__search" % field_name[1:]
+            else:
+                return "%s__icontains" % field_name
+            
         if self.lookup_opts.admin.search_fields and self.query:
             for bit in self.query.split():
-                or_queries = [models.Q(**{'%s__icontains' % field_name: bit}) for field_name in self.lookup_opts.admin.search_fields]
+                or_queries = [models.Q(**{construct_search(field_name): bit}) for field_name in self.lookup_opts.admin.search_fields]
                 other_qs = QuerySet(self.model)
                 other_qs = other_qs.filter(reduce(operator.or_, or_queries))
                 qs = qs & other_qs

File docs/model-api.txt

     class Manufacturer(models.Model):
         # ...
 
-Note, however, that you can only use strings to refer to models in the same 
-models.py file -- you cannot use a string to reference a model in a different 
+Note, however, that you can only use strings to refer to models in the same
+models.py file -- you cannot use a string to reference a model in a different
 application, or to reference a model that has been imported from elsewhere.
 
 Behind the scenes, Django appends ``"_id"`` to the field name to create its
 
 As with ``ForeignKey``, a relationship to self can be defined by using the
 string ``'self'`` instead of the model name, and you can refer to as-yet
-undefined models by using a string containing the model name. However, you 
-can only use strings to refer to models in the same models.py file -- you 
-cannot use a string to reference a model in a different application, or to 
+undefined models by using a string containing the model name. However, you
+can only use strings to refer to models in the same models.py file -- you
+cannot use a string to reference a model in a different application, or to
 reference a model that has been imported from elsewhere.
 
 It's suggested, but not required, that the name of a ``ManyToManyField``
     WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
     AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
 
+**New in Django development version:** For faster and/or more restrictive
+searches, prefix the field name with an operator:
+
+``^``
+    Matches the beginning of the field. For example, if ``search_fields`` is
+    set to ``['^first_name', '^last_name']`` and a user searches for
+    ``john lennon``, Django will do the equivalent of this SQL ``WHERE``
+    clause::
+
+        WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%')
+        AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')
+
+    This query is more efficient than the normal ``'%john%'`` query, because
+    the database only needs to check the beginning of a column's data, rather
+    than seeking through the entire column's data. Plus, if the column has an
+    index on it, some databases may be able to use the index for this query,
+    even though it's a ``LIKE`` query.
+
+``=``
+    Matches exactly, case-insensitive. For example, if
+    ``search_fields`` is set to ``['=first_name', '=last_name']`` and
+    a user searches for ``john lennon``, Django will do the equivalent
+    of this SQL ``WHERE`` clause::
+
+        WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john')
+        AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')
+
+    Note that the query input is split by spaces, so, following this example,
+    it's not currently not possible to search for all records in which
+    ``first_name`` is exactly ``'john winston'`` (containing a space).
+
+``@``
+    Performs a full-text match. This is like the default search method but uses
+    an index. Currently this is only available for MySQL.
+
 Managers
 ========