Skip to content

Instantly share code, notes, and snippets.

@karanlyons
Last active December 24, 2015 13:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karanlyons/6802835 to your computer and use it in GitHub Desktop.
Save karanlyons/6802835 to your computer and use it in GitHub Desktop.
Because setting up haystack would just be silly.
# -*- 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