
    Nwge                         d dl Z d dlZd dlmZ d dlmZmZ d dlmZ d dl	m
Z
mZ d dlmZ d dlmZmZ d dlmZ  G d	 d
      Z G d de      Z G d de      Z G d de      Z G d de      Zy)    N)reduce)connection_routerconnections)SQ)DEFAULT_OPERATORITERATOR_LOAD_PER_QUERY)
NotHandled)	AutoQueryRaw)logc                   N   e Zd ZdZd6dZd Zd Zd Zd Zd Z	d	 Z
d
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d  Z!d7d!Z"d" Z#d8d#Z$d$ Z%d% Z&d& Z'd' Z(d9d(Z)d) Z*d* Z+d+ Z,d, Z-d- Z.d. Z/d/ Z0d0 Z1d1 Z2d7d2Z3d3 Z4d4 Z5d7d5Z6y):SearchQuerySetz
    Provides a way to specify search parameters and lazily load results.

    Supports chaining (a la QuerySet) to narrow the search.
    Nc                     || _         d | _        | j                          ||| _        g | _        d | _        d| _        d| _        d| _        t        j                  d      | _
        y )NFr   haystack)_usingquery_determine_backend_result_cache_result_count_cache_full	_load_all_ignored_result_countlogging	getLoggerr   )selfusingr   s      E/var/www/horilla/myenv/lib/python3.12/site-packages/haystack/query.py__init__zSearchQuerySet.__init__   sf     
! DJ! %&"$$Z0    c                 t   | j                   't        | j                      j                         | _        y i }| j                  r| j                  j                  |d<   t        j                  di |}| j                  r!| j                  j                  |      | _        y t        |   j                         | _        y )Nmodels )r   r   	get_queryr   r!   r   for_readr   )r   hintsbackend_aliass      r   r   z!SearchQuerySet._determine_backend'   s    ;;"$T[[1;;=DJ ::"jj//E(O)22;U; ::))-8DJ$]3==?DJr   c                 d    t        |        | j                  j                         }d|d<   d|d<   |S )z
        For pickling.
        N_iterr   )len__dict__copy)r   obj_dicts     r   __getstate__zSearchQuerySet.__getstate__<   s5     	D	==%%' r   c                 F    || _         t        j                  d      | _        y)z!
        For unpickling.
        r   N)r*   r   r   r   )r   	data_dicts     r   __setstate__zSearchQuerySet.__setstate__F   s     "$$Z0r   c                 <    d| j                   d| j                  dS )Nz<SearchQuerySet: query=z, using=>)r   r   r   s    r   __repr__zSearchQuerySet.__repr__M   s    9=T[[QQr   c                     | j                   2| j                  j                         | _         | j                   sd| _         | j                   | j                  z
  S Nr   )r   r   	get_countr   r3   s    r   __len__zSearchQuerySet.__len__P   sO    %!%!5!5!7D %%%&" !!D$>$>>>r   c                 l    | j                         rt        | j                        S | j                         S N)_cache_is_fulliterr   _manual_iterr3   s    r   __iter__zSearchQuerySet.__iter__[   s.     **++  ""r   c                     t        |t              r|j                         S | j                         }|j                  j	                  |j                  t
        j                         |S r:   )
isinstanceEmptySearchQuerySet_cloner   combiner   ANDr   othercombineds      r   __and__zSearchQuerySet.__and__b   sE    e01<<>!;;=u{{BFF3r   c                     | j                         }t        |t              r|S |j                  j	                  |j                  t
        j                         |S r:   )rB   r@   rA   r   rC   r   ORrE   s      r   __or__zSearchQuerySet.__or__i   s>    ;;=e01Ou{{BEE2r   c                     | j                   j                         syt        |       dk  ry	 | j                  j	                  d        y# t
        $ r t        | j                        dkD  cY S w xY w)NFr   T)r   has_runr)   r   index
ValueErrorr3   s    r   r;   zSearchQuerySet._cache_is_fullp   sd    zz!!#t9>	/$$T* 	/t))*Q..	/s   A !A,+A,c              #   ^  K   d}d}	 t        | j                        dkD  r	 | j                  j                  d       }||k  r| j                  |    |dz  }||k  r| j	                         ry | j                  ||t        z         sy # t        $ r t        | j                        }Y mw xY ww)Nr      )r)   r   rN   rO   r;   _fill_cacher   )r   current_positioncurrent_cache_maxs      r   r=   zSearchQuerySet._manual_iter~   s     
 4%%&*@(,(:(:(@(@(F% #%66(()9:: A%  #%66 ""$ ## "25L"L '  " @(+D,>,>(?%@s-   B-B	  B-,B-	B*'B-)B**B-c                    g }| j                   r_i }i }|D ]7  }|j                  |j                  g       j                  |j                         9 |D ]  }| j                  |||         ||<    |D ]  }| j                   rj                  |j                  i       }|rJt        t        t        |                  } ||j                        |_        	 ||j                     |_
        n9| j                  d t        |      = | xj                  t        |      z  c_         |S |j                  |        |S # t        $ r2 | xj                  dz  c_        | j                  j                          Y w xY w)NrQ   )r   
setdefaultmodelappendpk_load_model_objectsgettypenextr<   _objectKeyErrorr   r   popr)   )	r   resultsto_cache
models_pksloaded_objectsresultrW   model_objectsresult_klasss	            r   post_process_resultsz#SearchQuerySet.post_process_results   ss    >>JN " J%%fllB7>>vyyIJ $ (,(@(@:e,)u%
  	$F~~ . 2 26<< D !#'T--@(A#BL ,VYY 7FI
!)6vyy)A **>S\>:..#g,>.  OOF#9	$< ' $ ! 22a72 **..0 !s   D558E0/E0c                 v   	 t         | j                  j                     j                         }|j	                  |      }|j                  | j                  j                        }|j                  |      S # t        $ r: | j                  j                  d|       |j                  j                  |      cY S w xY w)N)r   z&Model '%s' not handled by the routers.)r   r   r   get_unified_index	get_indexread_querysetin_bulkr	   r   warning_default_manager)r   rW   pksuirN   objectss         r   rZ   z"SearchQuerySet._load_model_objects   s    	7TZZ../AACBLL'E))

0A0A)BG??3'' 	7HHEuM))11#66	7s   A2A5 5A B87B8c                    | j                   j                          |d}|}|| j                  z  }|}||| j                  z  }| j                   j                  ||        | j                   j                  di |}|t        |      dk(  r| j                  d | | _        yt        | j                        dk(  r#d g| j                   j                         z  | _        ||}}|| j                   j                         }|}		 | j                  |      }
|
| j                  |	|	t        |
      z    d | j                  || v r|}|t        z  }|	t        |
      z  }	| j                   j                          | j                   j                  ||       | j                   j	                         }|t        |      dk(  r| j                  d |	 | _        	 y	 y)Nr   FTr"   )
r   _resetr   
set_limitsget_resultsr)   r   r7   rh   r   )r   startendkwargsquery_start	query_endra   
fill_startfill_endcache_startrb   s              r   rR   zSearchQuerySet._fill_cache   s   

=Et111	 333I

k95($**((262?c'la/!%!3!3FU!;D t!!"a'"&$***>*>*@!@D$cH
zz++-H 009H MUD{[3x=-HIt))%44%
33s8}, 

!!#

%%j(;**002?c'la&7)-););L[)ID&  / r   c                    t        |t        t        f      st        t        |t              s|dk\  sMt        |t              r6|j                  |j                  dk\  r|j
                  |j
                  dk\  sJ d       t        |t              r3d}|j                  }|j
                  t        |j
                        }nd}n	d}|}|dz   }t        | j                        dk  s!d| j                  || v r#| j                         s	 | j                  ||       |r| j                  || S | j                  |   S # t        $ r Y +w xY w)zE
        Retrieves an item or slice from the set of results.
        r   Nz#Negative indexing is not supported.TFrQ   )r@   sliceint	TypeErrorrw   stopr)   r   r;   rR   StopIteration)r   kis_slicerw   bounds        r   __getitem__zSearchQuerySet.__getitem__  s;    !eS\*Oq%(a1fq% AGGqL166Q;	1 1		1 
 aHGGEvv!AFFHEEE t!!"a'D&&uU33D<O<O<Q  . %%eE22!!%(( ! s   D7 7	EEc                 "    | j                         S )z"Returns all results for the query.)rB   r3   s    r   allzSearchQuerySet.all?  s    {{}r   c                 .    | j                  t              S )z+Returns an empty result list for the query.klass)rB   rA   r3   s    r   nonezSearchQuerySet.noneC  s    {{!4{55r   c                 \    t         dk(  r | j                  |i |S  | j                  |i |S )zHNarrows the search based on certain attributes and the default operator.rJ   )r   	filter_or
filter_and)r   argsry   s      r   filterzSearchQuerySet.filterG  s6    t#!4>>42622t///r   c                 p    | j                         }|j                  j                  t        |i |        |S )CNarrows the search by ensuring certain attributes are not included.rB   r   
add_filterr   r   r   ry   clones       r   excludezSearchQuerySet.excludeM  s1    D 3F 334r   c                 n    | j                         }|j                  j                  t        |i |       |S )zENarrows the search by looking for (and including) certain attributes.r   r   s       r   r   zSearchQuerySet.filter_andS  s.    r42623r   c                 r    | j                         }|j                  j                  t        |i |d       |S )r   T)use_orr   r   s       r   r   zSearchQuerySet.filter_orY  s3    r42624@r   c                 j    | j                         }|D ]  }|j                  j                  |        |S )z4Alters the order in which the results should appear.)rB   r   add_order_by)r   r   r   fields       r   order_byzSearchQuerySet.order_by_  s5     	,EKK$$U+	, r   c                 ^    | j                         } |j                  j                  di | |S )z!Adds highlighting to the results.r"   )rB   r   add_highlight)r   ry   r   s      r   	highlightzSearchQuerySet.highlighth  s)    !!!+F+r   c                    | j                         }|D ]q  }|t        | j                  j                     j	                         j                         vrt        j                  d|d       |j                  j                  |       s |S )zFAccepts an arbitrary number of Model classes to include in the search.z
The model z is not registered for search.)	rB   r   r   r   rj   get_indexed_modelswarningswarn	add_model)r   r!   r   rW   s       r   r!   zSearchQuerySet.modelsn  sr     		)E"4::#4#45""$##%&
 eUVKK!!%(		) r   c                 \    | j                         }|j                  j                  |       |S )z
        Allows specifying a different class to use for results.

        Overrides any previous usages. If ``None`` is provided, Haystack will
        revert back to the default ``SearchResult`` object.
        )rB   r   set_result_class)r   r   r   s      r   result_classzSearchQuerySet.result_class  s&     $$U+r   c                 ^    | j                         }|j                  j                  ||       |S )z%Boosts a certain aspect of the query.)rB   r   	add_boost)r   termboostr   s       r   r   zSearchQuerySet.boost  s&    dE*r   c                 `    | j                         } |j                  j                  |fi | |S )z0Adds faceting to a query for the provided field.)rB   r   add_field_facet)r   r   optionsr   s       r   facetzSearchQuerySet.facet  s+    ###E5W5r   c                 `    | j                         }|j                  j                  |||       |S )z1Spatial: Adds a bounding box search to the query.)rB   r   
add_within)r   r   point_1point_2r   s        r   withinzSearchQuerySet.within  s(    ugw7r   c                 `    | j                         }|j                  j                  |||       |S )z3Spatial: Adds a distance-based search to the query.)rB   r   add_dwithin)r   r   pointdistancer   s        r   dwithinzSearchQuerySet.dwithin  s(    uh7r   c                 (    | j                  |d      S )z-Adds stats to a query for the provided field.N)facet_fields)stats_facet)r   r   s     r   statszSearchQuerySet.stats  s    D99r   c                     | j                         }g }	 |j                  t        |g              |j                  j                  ||       |S # t        $ r |r|j                  |       Y <w xY w)z\Adds stats facet for the given field and facet_fields represents
        the faceted fields.)rB   rX   sumr   r   add_stats_query)r   r   r   r   stats_facetss        r   r   zSearchQuerySet.stats_facet  sl     	2L" 56 	##E<8	  	2##L1	2s   A A,+A,c                 ^    | j                         }|j                  j                  ||       |S )zk
        Spatial: Denotes results must have distance measurements from the
        provided point.
        )rB   r   add_distance)r   r   r   r   s       r   r   zSearchQuerySet.distance  s(    
   .r   c                 f    | j                         }|j                  j                  |||||       |S )z8Adds faceting to a query for the provided field by date.)
gap_amount)rB   r   add_date_facet)r   r   
start_dateend_dategap_byr   r   s          r   
date_facetzSearchQuerySet.date_facet  s6    "":xJ 	# 	
 r   c                 ^    | j                         }|j                  j                  ||       |S )zDAdds faceting to a query for the provided field with a custom query.)rB   r   add_query_facet)r   r   r   r   s       r   query_facetzSearchQuerySet.query_facet  s&    ##E51r   c                    t        |t              rE| j                  j                         }|j	                          |j                  |j                        }| j                         }|j                  j                  |       |S )z.Pushes existing facet choices into the search.)r@   r   r   rB   rt   as_query_stringbuild_query_fragmentadd_narrow_query)r   r   empty_queryr   s       r   narrowzSearchQuerySet.narrow  sd     eR **++-K ))+*J*JKE$$U+r   c                 :    | j                  t        |fi |      S )z+Passes a raw query directly to the backend.content)r   r   )r   query_stringry   s      r   
raw_searchzSearchQuerySet.raw_search  s    {{3|#>v#>{??r   c                 4    | j                         }d|_        |S )z8Efficiently populates the objects in the search results.T)rB   r   r   r   s     r   load_allzSearchQuerySet.load_all  s    r   c                 @    |t        |      i} | j                  di |S )z
        Performs a best guess constructing the search query.

        This method is somewhat naive but works well enough for the simple,
        common cases.
        r"   )r
   r   )r   r   	fieldnamery   s       r   
auto_queryzSearchQuerySet.auto_query  s'     Y|45t{{$V$$r   c           	      h   | j                         }g }|j                         D ]e  \  }}|j                  d      D ]L  }|j                  j	                  |j                               }|s/||i}|j                  t        di |       N g |j                  t        t        j                  |            S )z
        A shortcut method to perform an autocomplete search.

        Must be run against fields that are either ``NgramField`` or
        ``EdgeNgramField``.
         r"   )rB   itemssplitr   cleanstriprX   r   r   r   operatorrH   )r   ry   r   
query_bits
field_namer   wordbits           r   autocompletezSearchQuerySet.autocomplete  s     
!' 	4JC( 4kk''

5(#.F%%bl6l3	4	4 ||F8#3#3Z@AAr   c                 t    | j                         }| j                  j                  |      |_        ||_        |S )ze
        Allows switching which connection the ``SearchQuerySet`` uses to
        search in.
        )rB   r   r   r   )r   connection_namer   s      r   r   zSearchQuerySet.using  s1    
 jj&&7&r   c                     t        |       S )z-Returns the total number of matching results.)r)   r3   s    r   countzSearchQuerySet.count
  s    4yr   c                     | d   S )z:Returns the best/top search result that matches the query.r   r"   r3   s    r   
best_matchzSearchQuerySet.best_match  s    Awr   c                     | j                         }|j                  j                          |j                  j                  d|z         |j	                         S )z=Returns the most recent search result that matches the query.z-%s)rB   r   clear_order_byr   r   )r   
date_fieldr   s      r   latestzSearchQuerySet.latest  sC    ""$  !34!!r   c                 \    | j                         }|j                  j                  |       |S )z.Finds similar results to the object passed in.)rB   r   more_like_this)r   model_instancer   s      r   r   zSearchQuerySet.more_like_this  s$    "">2r   c                     | j                   j                         r| j                   j                         S | j                         }|j                   j                         S )z
        Returns the facet counts found by the query.

        This will cause the query to execute and should generally be used when
        presenting the data.
        )r   rM   get_facet_countsrB   r   s     r   facet_countszSearchQuerySet.facet_counts  sE     ::::..00KKME;;//11r   c                     | j                   j                         r| j                   j                         S | j                         }|j                   j                         S )z?
        Returns the stats results found by the query.
        )r   rM   	get_statsrB   r   s     r   stats_resultszSearchQuerySet.stats_results,  sE     ::::''))KKME;;((**r   c                 \    | j                         }|j                  j                  |       |S )a`  Set the exact text to be used to generate spelling suggestions

        When making complicated queries, such as the alt parser mechanism
        used by Solr dismax/edismax, this provides a convenient way to set
        the a simple text string which will be used to generate spelling
        suggestions without including unnecessary syntax.
        )rB   r   set_spelling_query)r   spelling_queryr   s      r   r  z!SearchQuerySet.set_spelling_query6  s&     &&~6r   c                     | j                   j                         r| j                   j                  |      S | j                         }|j                   j                  |      S )aN  
        Returns the spelling suggestion found by the query.

        To work, you must set ``INCLUDE_SPELLING`` within your connection's
        settings dictionary to ``True``. Otherwise, ``None`` will be returned.

        This will cause the query to execute and should generally be used when
        presenting the data.
        )r   rM   get_spelling_suggestionrB   )r   preferred_queryr   s      r   spelling_suggestionz"SearchQuerySet.spelling_suggestionB  sI     ::::55oFFKKME;;66GGr   c                 h    | j                  t              }|j                  j                  |       |S )z
        Returns a list of dictionaries, each containing the key/value pairs for
        the result, exactly like Django's ``ValuesQuerySet``.
        r   )rB   ValuesSearchQuerySet_fieldsextend)r   fieldsqss      r   valueszSearchQuerySet.valuesR  s,    
 [[3[4


&!	r   c                     |j                  dd      }|rt        |      dkD  rt        d      | j                  t              }|j
                  j                  |       ||_        |S )a)  
        Returns a list of field values as tuples, exactly like Django's
        ``QuerySet.values``.

        Optionally accepts a ``flat=True`` kwarg, which in the case of a
        single field being provided, will return a flat list of that field
        rather than a list of tuples.
        flatFrQ   zH'flat' is not valid when values_list is called with more than one field.r   )r`   r)   r   rB   ValuesListSearchQuerySetr  r  _flat)r   r  ry   r  r  s        r   values_listzSearchQuerySet.values_list[  sb     zz&%(CK!OZ  [[7[8


&!	r   c                     || j                   }| j                  j                         } ||      }| j                  |_        |S )N)r   )	__class__r   rB   r   )r   r   r   r   s       r   rB   zSearchQuerySet._cloner  s<    =NNE

!!#E"..r   )NNr:   )rQ   r   )7__name__
__module____qualname____doc__r   r   r-   r0   r4   r8   r>   rH   rK   r;   r=   rh   rZ   rR   r   r   r   r   r   r   r   r   r   r!   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r	  r  r  rB   r"   r   r   r   r      s   1&@*1R	?#/:0d	7:x()V60"	:@%B&"2+
H .r   r   c                   <     e Zd ZdZd Zd Zd fd	Zd Zd Z xZ	S )rA   z\
    A stubbed SearchQuerySet that behaves as normal but always returns no
    results.
    c                      yr6   r"   r3   s    r   r8   zEmptySearchQuerySet.__len__  s    r   c                      y)NTr"   r3   s    r   r;   z"EmptySearchQuerySet._cache_is_full  s    r   c                 6    t         |   |      }g |_        |S Nr   )superrB   r   r   r   r   r  s      r   rB   zEmptySearchQuerySet._clone  s     U+ r   c                      y)NFr"   )r   rw   rx   s      r   rR   zEmptySearchQuerySet._fill_cache  s    r   c                     i S r:   r"   r3   s    r   r   z EmptySearchQuerySet.facet_counts  s    	r   r:   )
r  r  r  r  r8   r;   rB   rR   r   __classcell__r  s   @r   rA   rA   |  s!    

r   rA   c                   >     e Zd ZdZ fdZd fd	Z fdZd Z xZS )r  z
    A ``SearchQuerySet`` which returns a list of field values as tuples, exactly
    like Django's ``ValuesListQuerySet``.
    c                 R    t        |   |i | d| _        g | _        g d| _        y )NF)id	django_ct	django_idscore)r!  r   r  r  _internal_fieldsr   r   ry   r  s      r   r   z!ValuesListSearchQuerySet.__init__  s.    $)&)

 !Jr   c                 l    t         |   |      }| j                  |_        | j                  |_        |S r   )r!  rB   r  r  r"  s      r   rB   zValuesListSearchQuerySet._clone  s.    U+jjr   c                     t        | j                        }|j                  | j                         d|i}t	        |   ||fi |S Nr  )setr-  updater  r!  rR   r   rw   rx   query_fieldsry   r  s        r   rR   z$ValuesListSearchQuerySet._fill_cache  sF    4001DLL)L)w"5#888r   c                     g }| j                   r|j                  }n|j                  }|D ]-  } || j                  D cg c]  }t	        ||d        c}       / |S c c}w r:   )r  r  rX   r  getattr)r   ra   rb   accumre   is         r   rh   z-ValuesListSearchQuerySet.post_process_results  s^    ::OOEOOE 	DFT\\B761d+BC	D  Cs   A
r:   )	r  r  r  r  r   rB   rR   rh   r%  r&  s   @r   r  r    s    
J9r   r  c                   (     e Zd ZdZ fdZd Z xZS )r  z
    A ``SearchQuerySet`` which returns a list of dictionaries, each containing
    the key/value pairs for the result, exactly like Django's
    ``ValuesQuerySet``.
    c                     t        | j                        }|j                  | j                         d|i}t	        t
        |   ||fi |S r1  )r2  r-  r3  r  r!  r  rR   r4  s        r   rR   z ValuesSearchQuerySet._fill_cache  sI    4001DLL)L)-t@VvVVr   c                     g }|D ]7  }|j                  | j                  D ci c]  }|t        ||d        c}       9 |S c c}w r:   )rX   r  r7  )r   ra   rb   re   r9  s        r   rh   z)ValuesSearchQuerySet.post_process_results  sN     	QFOO$,,OQQ4 88OP	Q  Ps   A
)r  r  r  r  rR   rh   r%  r&  s   @r   r  r    s    Wr   r  c                   :     e Zd ZdZ fdZd Zd Zd fd	Z xZS )RelatedSearchQuerySetzO
    A variant of the SearchQuerySet that can handle `load_all_queryset`s.
    c                 @    t        |   |i | i | _        g | _        y r:   )r!  r   _load_all_querysetsr   r.  s      r   r   zRelatedSearchQuerySet.__init__  s%    $)&)#% r   c                 8   || j                   v r| j                   |   j                  |      S 	 t        | j                  j                     j                         }|j                  |      }|j                         }|j                  |      S # t        $ r i cY S w xY wr:   )	r@  rm   r   r   r   rj   rk   load_all_querysetr	   )r   rW   rp   rq   rN   r  s         r   rZ   z)RelatedSearchQuerySet._load_model_objects  s    D,,,++E2::3??	 !2!23EEGU+,,.zz#&  		s   AB BBc                 D    | j                         }||j                  |<   |S )a(  
        Allows for specifying a custom ``QuerySet`` that changes how ``load_all``
        will fetch records for the provided model.

        This is useful for post-processing the results from the query, enabling
        things like adding ``select_related`` or filtering certain data.
        )rB   r@  )r   rW   querysetr   s       r   rB  z'RelatedSearchQuerySet.load_all_queryset  s$     +3!!%(r   c                 J    t         |   |      }| j                  |_        |S r   )r!  rB   r@  r"  s      r   rB   zRelatedSearchQuerySet._clone  s&    U+$($<$<!r   r:   )	r  r  r  r  r   rZ   rB  rB   r%  r&  s   @r   r>  r>    s!     
$
 r   r>  )r   r   	functoolsr   r   r   r   haystack.backendsr   haystack.constantsr   r   haystack.exceptionsr	   haystack.inputsr
   r   haystack.utilsr   r   r   rA   r  r  r>  r"   r   r   <module>rL     s_       3   H * * )l	 l	^. 2'~ 'T3 ,+N +r   