<s> from collections import defaultdict , namedtuple <EOL> import re <EOL> import inspect <EOL> BOOLEAN_FIELDS = ( <EOL> "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" <EOL> ) <EOL> DataColumn = namedtuple ( "<STR_LIT>" , ( "<STR_LIT:name>" , "<STR_LIT>" , "<STR_LIT>" ) ) <EOL> class DataTablesError ( ValueError ) : <EOL> pass <EOL> class DataTable ( object ) : <EOL> def __init__ ( self , params , model , query , columns ) : <EOL> self . params = params <EOL> self . model = model <EOL> self . query = query <EOL> self . data = { } <EOL> self . columns = [ ] <EOL> self . columns_dict = { } <EOL> self . search_func = lambda qs , s : qs <EOL> for col in columns : <EOL> name , model_name , filter_func = None , None , None <EOL> if isinstance ( col , DataColumn ) : <EOL> self . columns . append ( col ) <EOL> continue <EOL> elif isinstance ( col , tuple ) : <EOL> if len ( col ) == <NUM_LIT:3> : <EOL> name , model_name , filter_func = col <EOL> elif len ( col ) == <NUM_LIT:2> : <EOL> if callable ( col [ <NUM_LIT:1> ] ) : <EOL> name , filter_func = col <EOL> model_name = name <EOL> else : <EOL> name , model_name = col <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> else : <EOL> name , model_name = col , col <EOL> d = DataColumn ( name = name , model_name = model_name , filter = filter_func ) <EOL> self . columns . append ( d ) <EOL> self . columns_dict [ d . name ] = d <EOL> for column in ( col for col in self . columns if "<STR_LIT:.>" in col . model_name ) : <EOL> self . query = self . query . join ( column . model_name . split ( "<STR_LIT:.>" ) [ <NUM_LIT:0> ] , aliased = True ) <EOL> def query_into_dict ( self , key_start ) : <EOL> returner = defaultdict ( dict ) <EOL> pattern = "<STR_LIT>" . format ( key_start ) <EOL> columns = ( param for param in self . params if re . match ( pattern , param ) ) <EOL> for param in columns : <EOL> column_id , key , optional_subkey = re . search ( pattern , param ) . groups ( ) <EOL> if column_id is None : <EOL> returner [ key ] = self . coerce_value ( key , self . params [ param ] ) <EOL> elif optional_subkey is None : <EOL> returner [ int ( column_id ) ] [ key ] = self . coerce_value ( key , self . params [ param ] ) <EOL> else : <EOL> subdict = returner [ int ( column_id ) ] . setdefault ( key , { } ) <EOL> subdict [ optional_subkey ] = self . coerce_value ( "<STR_LIT>" . format ( key , optional_subkey ) , <EOL> self . params [ param ] ) <EOL> return dict ( returner ) <EOL> @ staticmethod <EOL> def coerce_value ( key , value ) : <EOL> try : <EOL> return int ( value ) <EOL> except ValueError : <EOL> if key in BOOLEAN_FIELDS : <EOL> return value == "<STR_LIT:true>" <EOL> return value <EOL> def get_integer_param ( self , param_name ) : <EOL> if param_name not in self . params : <EOL> raise DataTablesError ( "<STR_LIT>" . format ( param_name ) ) <EOL> try : <EOL> return int ( self . params [ param_name ] ) <EOL> except ValueError : <EOL> raise DataTablesError ( "<STR_LIT>" . format ( param_name ) ) <EOL> def add_data ( self , ** kwargs ) : <EOL> self . data . update ( ** kwargs ) <EOL> def json ( self ) : <EOL> try : <EOL> return self . _json ( ) <EOL> except DataTablesError as e : <EOL> return { <EOL> "<STR_LIT:error>" : str ( e ) <EOL> } <EOL> def get_column ( self , column ) : <EOL> if "<STR_LIT:.>" in column . model_name : <EOL> column_path = column . model_name . split ( "<STR_LIT:.>" ) <EOL> relationship = getattr ( self . model , column_path [ <NUM_LIT:0> ] ) <EOL> model_column = getattr ( relationship . property . mapper . entity , column_path [ <NUM_LIT:1> ] ) <EOL> else : <EOL> model_column = getattr ( self . model , column . model_name ) <EOL> return model_column <EOL> def searchable ( self , func ) : <EOL> self . search_func = func <EOL> def _json ( self ) : <EOL> draw = self . get_integer_param ( "<STR_LIT>" ) <EOL> start = self . get_integer_param ( "<STR_LIT:start>" ) <EOL> length = self . get_integer_param ( "<STR_LIT>" ) <EOL> columns = self . query_into_dict ( "<STR_LIT>" ) <EOL> ordering = self . query_into_dict ( "<STR_LIT>" ) <EOL> search = self . query_into_dict ( "<STR_LIT>" ) <EOL> query = self . query <EOL> total_records = query . count ( ) <EOL> if callable ( self . search_func ) and search . get ( "<STR_LIT:value>" , None ) : <EOL> query = self . search_func ( query , str ( search [ "<STR_LIT:value>" ] ) ) <EOL> for order in ordering . values ( ) : <EOL> direction , column = order [ "<STR_LIT>" ] , order [ "<STR_LIT>" ] <EOL> if column not in columns : <EOL> raise DataTablesError ( "<STR_LIT>" . format ( column ) ) <EOL> if not columns [ column ] [ "<STR_LIT>" ] : <EOL> continue <EOL> column_name = columns [ column ] [ "<STR_LIT:data>" ] <EOL> column = self . columns_dict [ column_name ] <EOL> model_column = self . get_column ( column ) <EOL> if isinstance ( model_column , property ) : <EOL> raise DataTablesError ( "<STR_LIT>" . format ( column . model_name ) ) <EOL> query = query . order_by ( model_column . desc ( ) if direction == "<STR_LIT>" else model_column . asc ( ) ) <EOL> filtered_records = query . count ( ) <EOL> query = query . slice ( start , start + length ) <EOL> return { <EOL> "<STR_LIT>" : draw , <EOL> "<STR_LIT>" : total_records , <EOL> "<STR_LIT>" : filtered_records , <EOL> "<STR_LIT:data>" : [ <EOL> self . output_instance ( instance ) for instance in query . all ( ) <EOL> ] <EOL> } <EOL> def output_instance ( self , instance ) : <EOL> returner = { <EOL> key . name : self . get_value ( key , instance ) for key in self . columns <EOL> } <EOL> if self . data : <EOL> returner [ "<STR_LIT>" ] = { <EOL> k : v ( instance ) for k , v in self . data . items ( ) <EOL> } <EOL> return returner <EOL> def get_value ( self , key , instance ) : <EOL> attr = key . model_name <EOL> if "<STR_LIT:.>" in attr : <EOL> tmp_list = attr . split ( "<STR_LIT:.>" ) <EOL> attr = tmp_list [ - <NUM_LIT:1> ] <EOL> for sub in tmp_list [ : - <NUM_LIT:1> ] : <EOL> instance = getattr ( instance , sub ) <EOL> if key . filter is not None : <EOL> r = key . filter ( instance ) <EOL> else : <EOL> r = getattr ( instance , attr ) <EOL> return r ( ) if inspect . isroutine ( r ) else r </s>
