Last active
December 24, 2015 13:09
-
-
Save karanlyons/6802835 to your computer and use it in GitHub Desktop.
Because setting up haystack would just be silly.
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
# -*- coding: utf-8 -*- | |
from __future__ import division, absolute_import, print_function, unicode_literals | |
import operator | |
from django.contrib.admin.util import lookup_needs_distinct | |
from django.contrib import admin | |
from django.db.models import Q | |
class StupidSearchAdmin(admin.ModelAdmin): | |
def get_search_results(self, request, queryset, search_term): | |
search_fields = self.get_search_fields(request) | |
if search_fields and search_term: | |
search_fields = set(search_fields) | |
django_style_search_fields = set([field for field in search_fields if field.startswith(('^', '=', '@'))]) | |
custom_search_fields = search_fields - django_style_search_fields | |
orm_lookups = set() | |
full_query = [] | |
custom_query = [] | |
django_query = [] | |
if custom_search_fields: | |
exact = [] | |
inexact = [] | |
exact_parts = [] | |
inexact_parts = [] | |
is_exact = False | |
for char in search_term: | |
if char == '"': | |
if is_exact: | |
is_exact = False | |
exact.append(''.join(exact_parts)) | |
exact_parts = [] | |
else: | |
is_exact = True | |
if inexact_parts: | |
inexact.extend(''.join(inexact_parts).split()) | |
inexact_parts = [] | |
else: | |
if is_exact: | |
exact_parts.append(char) | |
else: | |
inexact_parts.append(char) | |
if exact_parts: | |
inexact.extend(''.join(exact_parts).split()) | |
if inexact_parts: | |
inexact.extend(''.join(inexact_parts).split()) | |
if exact: | |
for exact_term in exact: | |
or_query = [] | |
for field in custom_search_fields: | |
orm_lookups.add('{}__contains'.format(field)) | |
or_query.append(Q(**{'{}__contains'.format(field): exact_term})) | |
custom_query.append(reduce(operator.or_, or_query)) | |
if inexact: | |
for inexact_term in inexact: | |
or_query = [] | |
for field in custom_search_fields: | |
orm_lookups.add('{}__icontains'.format(field)) | |
or_query.append(Q(**{'{}__icontains'.format(field): inexact_term})) | |
custom_query.append(reduce(operator.or_, or_query)) | |
if django_style_search_fields: | |
for term in search_term.split(): | |
or_query = [] | |
for field in django_style_search_fields: | |
if field.startswith('^'): | |
query = '{}__istartswith'.format(field[1:]) | |
elif field.startswith('='): | |
query = '{}__iexact'.format(field[1:]) | |
elif field.startswith('@'): | |
query = '{}__search'.format(field[1:]) | |
orm_lookups.add(query) | |
or_query.append(Q(**{query: term})) | |
django_query.append(reduce(operator.or_, or_query)) | |
if custom_query: | |
full_query.append(reduce(operator.and_, custom_query)) | |
if django_query: | |
full_query.append(reduce(operator.and_, django_query)) | |
return queryset.filter(reduce(operator.or_, full_query)), any((lookup_needs_distinct(self.opts, search_spec) for search_spec in orm_lookups)) | |
else: | |
return queryset, False |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment