Created
May 9, 2011 15:48
-
-
Save c4urself/962761 to your computer and use it in GitHub Desktop.
Search in multiple django models
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import operator | |
from django.db.models.query import QuerySet | |
from django.utils.encoding import smart_str | |
from django.db import models | |
def search_in_models(search_query, model_fields, queryset=False): | |
""" | |
Search in multiple models: | |
`model_fields` is are tuples within a tuple defining model_class, search_field pairs | |
((MyModel, ['field1', 'field2', '@field3']), | |
(MyOtherModel, ['field2']) | |
) | |
'@' = case insensitive search | |
'^' = case insensitive startswith | |
'=' = case insensitive exact | |
'' = case insensitive contains (default) | |
""" | |
def do_search(model_class, search_query, filter_fields, queryset): | |
qs = queryset if queryset else model_class._default_manager.all() | |
for bit in search_query.split(): | |
or_queries = [models.Q(**{construct_search( | |
smart_str(field_name)): smart_str(bit)}) | |
for field_name in filter_fields] | |
other_qs = QuerySet(model_class) | |
other_qs.dup_select_related(qs) | |
other_qs = other_qs.filter(reduce(operator.or_, or_queries)) | |
#limit results to items wihtin the original qs seeing as the original qs could have been filtered | |
qs = qs & other_qs | |
return other_qs | |
def construct_search(field_name): | |
# use different lookup methods depending on the notation | |
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 | |
final_search_result = [] | |
for model_field_pair in model_fields: | |
qs = do_search(model_field_pair[0], search_query, model_field_pair[1], queryset) | |
for qs_item in qs: | |
qfinal_search_result.append(qs_item) | |
return final_search_result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment