<s> from __future__ import absolute_import , unicode_literals <EOL> import datetime <EOL> import logging <EOL> import re <EOL> from django . apps import apps <EOL> from django . core . exceptions import PermissionDenied <EOL> from django . db . models import Q <EOL> from django . utils . module_loading import import_string <EOL> from acls . models import AccessControlList <EOL> from permissions import Permission <EOL> from . models import RecentSearch <EOL> from . settings import setting_limit <EOL> logger = logging . getLogger ( __name__ ) <EOL> class SearchModel ( object ) : <EOL> registry = { } <EOL> @ classmethod <EOL> def get ( cls , full_name ) : <EOL> result = cls . registry [ full_name ] <EOL> if not hasattr ( result , '<STR_LIT>' ) : <EOL> result . serializer = import_string ( result . serializer_string ) <EOL> return result <EOL> def __init__ ( self , app_label , model_name , serializer_string , label = None , permission = None ) : <EOL> self . app_label = app_label <EOL> self . model_name = model_name <EOL> self . search_fields = [ ] <EOL> self . model = None <EOL> self . label = label <EOL> self . serializer_string = serializer_string <EOL> self . permission = permission <EOL> self . __class__ . registry [ self . get_full_name ( ) ] = self <EOL> def get_full_name ( self ) : <EOL> return '<STR_LIT>' % ( self . app_label , self . model_name ) <EOL> def get_all_search_fields ( self ) : <EOL> return self . search_fields <EOL> def get_search_field ( self , full_name ) : <EOL> try : <EOL> return self . search_fields [ full_name ] <EOL> except KeyError : <EOL> raise KeyError ( '<STR_LIT>' % full_name ) <EOL> def get_fields_simple_list ( self ) : <EOL> """<STR_LIT>""" <EOL> result = [ ] <EOL> for search_field in self . get_all_search_fields ( ) : <EOL> result . append ( ( search_field . get_full_name ( ) , search_field . label ) ) <EOL> return result <EOL> def add_model_field ( self , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> search_field = SearchField ( self , * args , ** kwargs ) <EOL> self . search_fields . append ( search_field ) <EOL> def normalize_query ( self , query_string , <EOL> findterms = re . compile ( r'<STR_LIT>' ) . findall , <EOL> normspace = re . compile ( r'<STR_LIT>' ) . sub ) : <EOL> """<STR_LIT>""" <EOL> return [ <EOL> normspace ( '<STR_LIT:U+0020>' , ( t [ <NUM_LIT:0> ] or t [ <NUM_LIT:1> ] ) . strip ( ) ) for t in findterms ( query_string ) <EOL> ] <EOL> def search ( self , query_string , user , global_and_search = False ) : <EOL> elapsed_time = <NUM_LIT:0> <EOL> start_time = datetime . datetime . now ( ) <EOL> result_set = set ( ) <EOL> search_dict = { } <EOL> if not self . model : <EOL> self . model = apps . get_model ( self . app_label , self . model_name ) <EOL> if not self . label : <EOL> self . label = self . model . _meta . verbose_name <EOL> if '<STR_LIT:q>' in query_string : <EOL> for search_field in self . get_all_search_fields ( ) : <EOL> search_dict . setdefault ( search_field . get_model ( ) , { <EOL> '<STR_LIT>' : [ ] , <EOL> '<STR_LIT:label>' : search_field . label , <EOL> '<STR_LIT>' : search_field . return_value <EOL> } ) <EOL> search_dict [ search_field . get_model ( ) ] [ '<STR_LIT>' ] . append ( <EOL> { <EOL> '<STR_LIT>' : [ search_field . field ] , <EOL> '<STR_LIT>' : self . normalize_query ( <EOL> query_string . get ( '<STR_LIT:q>' , '<STR_LIT>' ) . strip ( ) <EOL> ) <EOL> } <EOL> ) <EOL> else : <EOL> for search_field in self . get_all_search_fields ( ) : <EOL> if search_field . field in query_string and query_string [ search_field . field ] : <EOL> search_dict . setdefault ( search_field . get_model ( ) , { <EOL> '<STR_LIT>' : [ ] , <EOL> '<STR_LIT:label>' : search_field . label , <EOL> '<STR_LIT>' : search_field . return_value <EOL> } ) <EOL> search_dict [ search_field . get_model ( ) ] [ '<STR_LIT>' ] . append ( <EOL> { <EOL> '<STR_LIT>' : [ search_field . field ] , <EOL> '<STR_LIT>' : self . normalize_query ( <EOL> query_string [ search_field . field ] <EOL> ) <EOL> } <EOL> ) <EOL> for model , data in search_dict . items ( ) : <EOL> logger . debug ( '<STR_LIT>' , model ) <EOL> model_result_set = set ( ) <EOL> for query_entry in data [ '<STR_LIT>' ] : <EOL> field_query_list = self . assemble_query ( <EOL> query_entry [ '<STR_LIT>' ] , query_entry [ '<STR_LIT>' ] <EOL> ) <EOL> logger . debug ( '<STR_LIT>' , field_query_list ) <EOL> field_result_set = set ( ) <EOL> for query in field_query_list : <EOL> logger . debug ( '<STR_LIT>' , query ) <EOL> term_query_result_set = set ( <EOL> model . objects . filter ( query ) . values_list ( <EOL> data [ '<STR_LIT>' ] , flat = True <EOL> ) <EOL> ) <EOL> if not field_result_set : <EOL> field_result_set = term_query_result_set <EOL> else : <EOL> field_result_set &= term_query_result_set <EOL> logger . debug ( <EOL> '<STR_LIT>' , term_query_result_set <EOL> ) <EOL> logger . debug ( '<STR_LIT>' , field_result_set ) <EOL> if global_and_search : <EOL> if not model_result_set : <EOL> model_result_set = field_result_set <EOL> else : <EOL> model_result_set &= field_result_set <EOL> else : <EOL> model_result_set |= field_result_set <EOL> result_set = result_set | model_result_set <EOL> elapsed_time = unicode ( <EOL> datetime . datetime . now ( ) - start_time <EOL> ) . split ( '<STR_LIT::>' ) [ <NUM_LIT:2> ] <EOL> queryset = self . model . objects . filter ( <EOL> pk__in = list ( result_set ) [ : setting_limit . value ] <EOL> ) <EOL> if self . permission : <EOL> try : <EOL> Permission . check_permissions ( user , [ self . permission ] ) <EOL> except PermissionDenied : <EOL> queryset = AccessControlList . objects . filter_by_access ( <EOL> self . permission , user , queryset <EOL> ) <EOL> RecentSearch . objects . add_query_for_user ( <EOL> user , query_string , len ( result_set ) <EOL> ) <EOL> return queryset , result_set , elapsed_time <EOL> def assemble_query ( self , terms , search_fields ) : <EOL> """<STR_LIT>""" <EOL> queries = [ ] <EOL> for term in terms : <EOL> or_query = None <EOL> for field in search_fields : <EOL> q = Q ( ** { '<STR_LIT>' % ( field , '<STR_LIT>' ) : term } ) <EOL> if or_query is None : <EOL> or_query = q <EOL> else : <EOL> or_query = or_query | q <EOL> queries . append ( or_query ) <EOL> return queries <EOL> class SearchField ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , search_model , field , label ) : <EOL> self . search_model = search_model <EOL> self . field = field <EOL> self . label = label <EOL> self . return_value = '<STR_LIT>' <EOL> def get_full_name ( self ) : <EOL> return self . field <EOL> def get_model ( self ) : <EOL> return self . search_model . model </s>
