#NEWLINE# def build_filter( self , filter_expr , branch_negated = False , current_negated = False , can_reuse = None ) : #NEWLINE# #INDENT# "\n        Builds a WhereNode for a single filter clause, but doesn't add it\n        to this Query. Query.add_q() will then add this filter to the where\n        or having Node.\n\n        The 'branch_negated' tells us if the current branch contains any\n        negations. This will be used to determine if subqueries are needed.\n\n        The 'current_negated' is used to determine if the current filter is\n        negated or not and this will be used to determine if IS NULL filtering\n        is needed.\n\n        The difference between current_netageted and branch_negated is that\n        branch_negated is set on first negation, but current_negated is\n        flipped for each negation.\n\n        Note that add_filter will not do any negating itself, that is done\n        upper in the code by add_q().\n\n        The 'can_reuse' is a set of reusable joins for multijoins.\n\n        The method will create a filter clause that can be added to the current\n        query. However, if the filter isn't added to the query then the caller\n        is responsible for unreffing the joins used.\n        " #NEWLINE# ( arg , value ) = filter_expr #NEWLINE# parts = arg . split ( LOOKUP_SEP ) #NEWLINE# if ( not parts ) : #NEWLINE# #INDENT# raise FieldError ( ( 'Cannot parse keyword query %r' % arg ) ) #NEWLINE# #UNINDENT# lookup_type = 'exact' #NEWLINE# num_parts = len ( parts ) #NEWLINE# if ( ( len ( parts ) > 1 ) and ( parts [ ( - 1 ) ] in self . query_terms ) and ( arg not in self . aggregates ) ) : #NEWLINE# #INDENT# lookup_model = self . model #NEWLINE# for ( counter , field_name ) in enumerate ( parts ) : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# lookup_field = lookup_model . _meta . get_field ( field_name ) #NEWLINE# #UNINDENT# except FieldDoesNotExist : #NEWLINE# #INDENT# lookup_type = parts . pop ( ) #NEWLINE# break #NEWLINE# #UNINDENT# if ( ( counter + 1 ) < num_parts ) : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# lookup_model = lookup_field . rel . to #NEWLINE# #UNINDENT# except AttributeError : #NEWLINE# #INDENT# lookup_type = parts . pop ( ) #NEWLINE# break #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# clause = self . where_class ( ) #NEWLINE# if ( value is None ) : #NEWLINE# #INDENT# if ( lookup_type != 'exact' ) : #NEWLINE# #INDENT# raise ValueError ( 'Cannot use None as a query value' ) #NEWLINE# #UNINDENT# lookup_type = 'isnull' #NEWLINE# value = True #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if callable ( value ) : #NEWLINE# #INDENT# value = value ( ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if isinstance ( value , ExpressionNode ) : #NEWLINE# #INDENT# value = SQLEvaluator ( value , self , reuse = can_reuse ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# if ( connections [ DEFAULT_DB_ALIAS ] . features . interprets_empty_strings_as_nulls and ( lookup_type == 'exact' ) and ( value == '' ) ) : #NEWLINE# #INDENT# value = True #NEWLINE# lookup_type = 'isnull' #NEWLINE# #UNINDENT# for ( alias , aggregate ) in self . aggregates . items ( ) : #NEWLINE# #INDENT# if ( alias in ( parts [ 0 ] , LOOKUP_SEP . join ( parts ) ) ) : #NEWLINE# #INDENT# clause . add ( ( aggregate , lookup_type , value ) , AND ) #NEWLINE# return clause #NEWLINE# #UNINDENT# #UNINDENT# opts = self . get_meta ( ) #NEWLINE# alias = self . get_initial_alias ( ) #NEWLINE# allow_many = ( not branch_negated ) #NEWLINE# try : #NEWLINE# #INDENT# ( field , sources , opts , join_list , path ) = self . setup_joins ( parts , opts , alias , can_reuse , allow_many , allow_explicit_fk = True ) #NEWLINE# if ( can_reuse is not None ) : #NEWLINE# #INDENT# can_reuse . update ( join_list ) #NEWLINE# #UNINDENT# self . _lookup_joins = join_list #NEWLINE# #UNINDENT# except MultiJoin as e : #NEWLINE# #INDENT# return self . split_exclude ( filter_expr , LOOKUP_SEP . join ( parts [ : e . level ] ) , can_reuse , e . names_with_path ) #NEWLINE# #UNINDENT# if ( ( lookup_type == 'isnull' ) and ( value is True ) and ( not current_negated ) and ( len ( join_list ) > 1 ) ) : #NEWLINE# #INDENT# self . promote_joins ( join_list ) #NEWLINE# #UNINDENT# ( targets , alias , join_list ) = self . trim_joins ( sources , join_list , path ) #NEWLINE# if hasattr ( field , 'get_lookup_constraint' ) : #NEWLINE# #INDENT# constraint = field . get_lookup_constraint ( self . where_class , alias , targets , sources , lookup_type , value ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# constraint = ( Constraint ( alias , targets [ 0 ] . column , field ) , lookup_type , value ) #NEWLINE# #UNINDENT# clause . add ( constraint , AND ) #NEWLINE# if ( current_negated and ( ( lookup_type != 'isnull' ) or ( value is False ) ) ) : #NEWLINE# #INDENT# self . promote_joins ( join_list ) #NEWLINE# if ( ( lookup_type != 'isnull' ) and ( self . is_nullable ( targets [ 0 ] ) or ( self . alias_map [ join_list [ ( - 1 ) ] ] . join_type == self . LOUTER ) ) ) : #NEWLINE# #INDENT# clause . add ( ( Constraint ( alias , targets [ 0 ] . column , None ) , 'isnull' , False ) , AND ) #NEWLINE# #UNINDENT# #UNINDENT# return clause