3

I have a single model in my django app that I want to create a search form for. Is there a way to search all the fields in the model at once with the same search string? I've looked into xapian and solr but they seem like a lot of overhead for searching over 1 model. I want to be able to say something like:

results = Assignment.objects.filter(any_column = search_string)

I realize there might not be something that concise but right now the only option I can come up with other than using a search app is to check each field separately and concatenate the results together.

Matt Phillips
  • 11,249
  • 10
  • 46
  • 71

2 Answers2

13

Once you have all the field names you can create Q objects using kwarg expansion and use reduce() along with operator.or_ to turn them into a single query.

qgroup = reduce(operator.or_, (Q(**{fieldname: value}) for fieldname in fieldnames))
asgns = Assignment.objects.filter(qgroup)
Community
  • 1
  • 1
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 1
    I had to add parenthesis around the Q(...) objects but otherwise this worked like a charm! Thank you. Is there a reason why something like this isn't made into a shortcut in django. You would think for searching simple models like this having syntax like my initial example would be a great tool right? – Matt Phillips Dec 20 '10 at 06:12
  • Dunno. Probably because it's trivial to do with Python. – Ignacio Vazquez-Abrams Dec 20 '10 at 06:16
  • So you would say that `qgroup = reduce(operator.or_, Q(**{fieldname: value}) for fieldname in fieldnames)` would be trivial for a django programmer versus having `Assignment.objects.filter(any_column='somestring')` being part of the API ? Interesting... I know it may not be trivial to implement on the django side but I just think it would be a common usage for searching models. – Matt Phillips Dec 20 '10 at 06:21
  • It would be trivial for a Python programmer. And not something a Django programmer would need often. – Ignacio Vazquez-Abrams Dec 20 '10 at 06:22
  • It may be trivial to do with python, but sql is waay faster – danbgray Jan 03 '13 at 19:57
  • 1
    @danbgray: The ORM is manipulated in Python, but it generates SQL regardless. – Ignacio Vazquez-Abrams Jan 03 '13 at 19:58
  • 1
    In Python 3.x reduce was moved from the built-in functions to the functools module – Paulo Scardine Jul 03 '13 at 12:43
  • 1
    This generated repeated results for me. This way, if the value/term appears in different fields, the query returns the same object many times (once per field). How to solve that? – marcelosalloum Jan 15 '14 at 15:45
0

Old question, but for further reference I am adding this:

In django 1.10 SearchVector class was added.

Usage from the docs:

Searching against a single field is great but rather limiting. The Entry instances we’re searching belong to a Blog, which has a tagline field. To query against both fields, use a SearchVector:

>>> from django.contrib.postgres.search import SearchVector
>>> Entry.objects.annotate(
...     search=SearchVector('body_text', 'blog__tagline'),
... ).filter(search='Cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]
redacted
  • 3,789
  • 6
  • 25
  • 38