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

git-svn-id: http://code.djangoproject.com/svn/django/trunk@3601 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-08-18 02:48:34 +00:00
parent eefe35c7fa
commit efa19ae8a7
3 changed files with 52 additions and 6 deletions

View File

@ -68,6 +68,7 @@ answer newbie questions, and generally made Django that much better:
deric@monowerks.com deric@monowerks.com
dne@mayonnaise.net dne@mayonnaise.net
Jeremy Dunck <http://dunck.us/> Jeremy Dunck <http://dunck.us/>
Andy Dustman <farcepest@gmail.com>
Clint Ecker Clint Ecker
gandalf@owca.info gandalf@owca.info
Baishampayan Ghose Baishampayan Ghose

View File

@ -711,9 +711,19 @@ class ChangeList(object):
qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field) qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field)
# Apply keyword searches. # 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: if self.lookup_opts.admin.search_fields and self.query:
for bit in self.query.split(): 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 = QuerySet(self.model)
other_qs = other_qs.filter(reduce(operator.or_, or_queries)) other_qs = other_qs.filter(reduce(operator.or_, or_queries))
qs = qs & other_qs qs = qs & other_qs

View File

@ -686,8 +686,8 @@ you can use the name of the model, rather than the model object itself::
class Manufacturer(models.Model): class Manufacturer(models.Model):
# ... # ...
Note, however, that you can only use strings to refer to models in the same 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 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. 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 Behind the scenes, Django appends ``"_id"`` to the field name to create its
@ -810,9 +810,9 @@ here's how you'd represent that::
As with ``ForeignKey``, a relationship to self can be defined by using the 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 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 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 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 cannot use a string to reference a model in a different application, or to
reference a model that has been imported from elsewhere. reference a model that has been imported from elsewhere.
It's suggested, but not required, that the name of a ``ManyToManyField`` It's suggested, but not required, that the name of a ``ManyToManyField``
@ -1386,6 +1386,41 @@ user searches for ``john lennon``, Django will do the equivalent of this SQL
WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%') WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%') 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 Managers
======== ========