
    NwgI                     N   d dl Z d dlZd dlZd dl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mZmZ d dlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm Z m!Z! d dl"m#Z# d d	l$m%Z%m&Z&m'Z'  G d
 de(      Z) G d dejT                  e)      Z+ G d de+      Z,efdZ- G d de+      Z.y)    N)ImproperlyConfigured)	force_str)connection_routerconnections)	Indexable)DEFAULT_ALIAS	DJANGO_CT	DJANGO_IDID)BooleanField	CharField	DateFieldDateTimeFieldDecimalFieldEdgeNgramFieldFacetCharFieldFacetDateFieldFacetDateTimeFieldFacetIntegerField
FloatFieldIntegerFieldLocationFieldMultiValueField
NgramFieldSearchFieldSearchFieldError)SearchIndexManager)get_facet_field_nameget_identifierget_model_ctc                        e Zd Z fdZ xZS )DeclarativeMetaclassc                    i |d<   	 |D cg c]  }t        |t              s| }}|j                          |D ]&  }t        |dd       }|s|d   j	                  |       ( 	 i }|j                         D ]M  \  }	}
t        |
d      s|
j                  |vrg ||
j                  <   ||
j                     j                  |	       O i }|j                         D ]  \  }	}
t        |
t              s||	   }|j                  |	       |||	<   t        |d      r?|j                  sL|	|vsQt        |	      }|j                  |	      }|j                  |       |||<    |d   j	                  |       d|vr	 t!        |d   j"                        |d<   t*        t,        | _  | |||      S c c}w # t
        $ r Y Uw xY w# t$        t&        f$ r t!        t(              |d<   Y Nw xY w)Nfields	facet_for)r%   objectsMeta)
issubclassSearchIndexreversegetattrupdate	NameErroritemshasattrr%   append
isinstancer   set_instance_namefacetedr   facet_classr   index_labelKeyErrorAttributeErrorr   superr"   __new__)clsnamebasesattrsbparentspr$   facet_fields
field_nameobjbuilt_fieldsfieldshadow_facet_nameshadow_facet_field	__class__s                  G/var/www/horilla/myenv/lib/python3.12/site-packages/haystack/indexes.pyr9   zDeclarativeMetaclass.__new__#   s   h	"'FQ:a+EqFGFOO 3 Hd3(O**62	3 ${{} 	?OJsK(==424L/S]]+22:>	? ${{} 	QOJ#{+j)''
3+0Z( uk2}} &\90DZ0P-161B1BZ1B1X..@@ARS>PL):;	Q" 	h|, E!E#5eFm6O6O#Pi  )37T5%PPg G  		N n- E#5m#Di Es>   F- F(F(&F- F- 7F= (F- -	F:9F:=!G! G!)__name__
__module____qualname__r9   __classcell__rH   s   @rI   r"   r"   "   s    8Q 8Q    r"   c                       e Zd ZdZd Zd ZddZddZddZd Z	dd	Z
d
 Zd Zd ZddZddZddZddZddZddZd Zd Zd Zy)r)   a  
    Base class for building indexes.

    An example might look like this::

        import datetime
        from haystack import indexes
        from myapp.models import Note

        class NoteIndex(indexes.SearchIndex, indexes.Indexable):
            text = indexes.CharField(document=True, use_template=True)
            author = indexes.CharField(model_attr='user')
            pub_date = indexes.DateTimeField(model_attr='pub_date')

            def get_model(self):
                return Note

            def index_queryset(self, using=None):
                return self.get_model().objects.filter(pub_date__lte=datetime.datetime.now())

    c                 :   d | _         g }i | _        | j                  j                         D ]>  \  }}|| j                  |j                  <   |j
                  du s.|j                  |       @ t        |      dk(  s"t        d| j                  j                  z        y )NT   KThe index '%s' must have one (and only one) SearchField with document=True.)prepared_data	field_mapr$   r.   index_fieldnamedocumentr0   lenr   rH   rJ   )selfcontent_fieldsrB   rE   s       rI   __init__zSearchIndex.__init__u   s    !!%!2!2!4 	2J4>DNN5001~~%%%j1		2 >"a'"]..))*  (rO   c                     t        d| z        )z
        Should return the ``Model`` class (not an instance) that the rest of the
        ``SearchIndex`` should use.

        This method is required & you must override it to return the correct class.
        z9You must provide a 'get_model' method for the '%r' index.)NotImplementedErrorrY   s    rI   	get_modelzSearchIndex.get_model   s     "G$N
 	
rO   Nc                 R    | j                         j                  j                         S )z
        Get the default QuerySet to index when doing a full update.

        Subclasses can override this method to avoid indexing certain objects.
        r_   _default_managerallrY   usings     rI   index_querysetzSearchIndex.index_queryset   s      ~~004466rO   c                 &    | j                  |      S )z
        Get the default QuerySet for read actions.

        Subclasses can override this method to work with other managers.
        Useful when working with default managers that filter some objects.
        re   )rf   rd   s     rI   read_querysetzSearchIndex.read_queryset   s     """//rO   c                 *   i }| j                         }| j                         }d|j                  z  }|r |r	||d|z  <   nt        j                  |       |r |r	||d|z  <   nt        j                  |       d}t        | d      r&t        j                  d       | j                         }n| j                  |      }t        |d      st        d	| z         |j                  d
i |j                  |j                  j                  j                        S )a7  
        Get the default QuerySet to index when doing an index update.

        Subclasses can override this method to take into account related
        model modification times.

        The default is to use ``SearchIndex.index_queryset`` and filter
        based on ``SearchIndex.get_updated_field``
        z>No updated date field found for '%s' - not restricting by age.z%s__gtez%s__lteNget_querysetzd'SearchIndex.get_queryset' was deprecated in Haystack v2. Please rename the method 'index_queryset'.rh   filterzGThe '%r' class must return a 'QuerySet' in the 'index_queryset' method. )r_   get_updated_fieldrJ   warningswarnr/   rk   rf   r   rl   order_by_metapkr;   )	rY   re   
start_dateend_dateextra_lookup_kwargsmodelupdated_fieldupdate_field_msgindex_qss	            rI   build_querysetzSearchIndex.build_queryset   s    ! ..0 PNN AK#I$=>./AI#I$=>./4(MM> ((*H***7Hx*&Y  x5!45>>u{{~~?R?RSSrO   c                    t         t        |      t        t        | j	                               t
        t        |j                        i| _        | j                  j                         D ]k  \  }}|j                  |      | j                  |j                  <   t        | d|z        s> t        | d|z        |      }|| j                  |j                  <   m | j                  S )z?
        Fetches and adds/alters data before indexing.
        z
prepare_%s)r   r   r	   r    r_   r
   r   rs   rT   r$   r.   preparerV   r/   r+   )rY   rC   rB   rE   values        rI   r}   zSearchIndex.prepare   s    
 s#|DNN$45y(
 "&!2!2!4 	BJ 9>c8JDu445t\J67@lZ&?@E<A""5#8#89	B !!!rO   c                 F   | j                  |      | _        | j                  j                         D ]  \  }}|s)|j                  dk(  rt        |dd       | j                  v r1t        |dd       rf| j                  |j                     j                  }| j                  |   4|| j                  v r&| j                  |   | j                  |j                  <   |j                  du s| j                  |j                     | j                  |j                  =  | j                  S )Nstringr%   T)	r}   rT   r$   r.   
field_typer+   r%   rV   null)rY   rC   with_string_facetrB   rE   source_field_names         rI   full_preparezSearchIndex.full_prepare   s   !\\#.!%!2!2!4 	BJ &$$0E;5Duk40$(KK$@$P$P!
 &&z2:)T-?-??@D@R@R)AD&&u'<'<=
 zzT!%%e&;&;<D**5+@+@A1	B4 !!!rO   c                     | j                   j                         D ]!  \  }}|j                  du s|j                  c S  y)zCReturns the field that supplies the primary document to be indexed.TN)r$   r.   rW   rV   )rY   _rE   s      rI   get_content_fieldzSearchIndex.get_content_field	  s:    ))+ 	-HAu~~%,,,	-rO   c                     i }| j                   j                         D ]!  \  }}|j                  s|j                  ||<   # |S )z+Returns a dict of fields with weight values)r$   r.   boost)rY   weightsrB   rE   s       rI   get_field_weightszSearchIndex.get_field_weights  sD    !%!2!2!4 	2J{{&+kk
#	2 rO   c                 X    t        j                  dt               | j                  |      S )NzKSearchIndex._get_backend is deprecated; use SearchIndex.get_backend instead)ro   rp   DeprecationWarningget_backendrd   s     rI   _get_backendzSearchIndex._get_backend  s'    Y	
 &&rO   c                     |	 t        j                  |       d   }t        |   j	                         S # t        $ r Y y w xY w)N)indexr   )r   	for_write
IndexErrorr   r   rd   s     rI   r   zSearchIndex.get_backend  sK    =)33$?B
 5!--//	  s   4 	A A c                 p    | j                  |      }|#|j                  | | j                  |             yy)z
        Updates the entire index.

        If ``using`` is provided, it specifies which connection should be
        used. Default relies on the routers to decide which backend should
        be used.
        Nrh   )r   r,   rf   rY   re   backends      rI   r,   zSearchIndex.update(  s;     ""5)NN4!4!45!4!AB rO   c                 z     | j                   |fi |r(| j                  |      }||j                  | |g       yyy)a  
        Update the index for a single object. Attached to the class's
        post-save hook.

        If ``using`` is provided, it specifies which connection should be
        used. Default relies on the routers to decide which backend should
        be used.
        N)should_updater   r,   rY   instancere   kwargsr   s        rI   update_objectzSearchIndex.update_object6  sI     4h1&1&&u-G"thZ0 # 2rO   c                 R    | j                  |      }| |j                  |fi | yy)a  
        Remove an object from the index. Attached to the class's
        post-delete hook.

        If ``using`` is provided, it specifies which connection should be
        used. Default relies on the routers to decide which backend should
        be used.
        N)r   remover   s        rI   remove_objectzSearchIndex.remove_objectF  s2     ""5)GNN8.v. rO   c                 n    | j                  |      }|"|j                  | j                         g       yy)z
        Clears the entire index.

        If ``using`` is provided, it specifies which connection should be
        used. Default relies on the routers to decide which backend should
        be used.
        N)models)r   clearr_   r   s      rI   r   zSearchIndex.clearT  s7     ""5)MM$.."2!3M4 rO   c                 L    | j                  |       | j                  |       y)z
        Completely clear the index for this model and rebuild it.

        If ``using`` is provided, it specifies which connection should be
        used. Default relies on the routers to decide which backend should
        be used.
        rh   N)r   r,   rd   s     rI   reindexzSearchIndex.reindexa  s      	


% rO   c                      y)ax  
        Get the field name that represents the updated date for the model.

        If specified, this is used by the reindex command to filter out results
        from the QuerySet, enabling you to reindex only recent records. This
        method should either return None (reindex everything always) or a
        string of the Model's DateField/DateTimeField name.
        Nrm   r^   s    rI   rn   zSearchIndex.get_updated_fieldl  s     rO   c                      y)aN  
        Determine if an object should be updated in the index.

        It's useful to override this when an object may save frequently and
        cause excessive reindexing. You should check conditions on the instance
        and return False if it is not to be indexed.

        By default, returns True (always reindex).
        Trm   )rY   r   r   s      rI   r   zSearchIndex.should_updatew  s     rO   c                 R    | j                         j                  j                         S )ac  
        Provides the ability to override how objects get loaded in conjunction
        with ``SearchQuerySet.load_all``.

        This is useful for post-processing the results from the query, enabling
        things like adding ``select_related`` or filtering certain data.

        By default, returns ``all()`` on the model's default manager.
        ra   r^   s    rI   load_all_querysetzSearchIndex.load_all_queryset  s      ~~004466rO   N)NNN)T)rJ   rK   rL   __doc__r[   r_   rf   ri   r{   r}   r   r   r   r   r   r,   r   r   r   r   rn   r   r   rm   rO   rI   r)   r)   ^   si    ,"	
701Tf"*">-'0C1 /5	!	

7rO   r)   )	metaclassc                        e Zd Z edd      Zy)BasicSearchIndexTrW   use_templateN)rJ   rK   rL   r   textrm   rO   rI   r   r     s    d6DrO   r   c                 
   |}| j                         dv rt        }|S | j                         dv rt        }|S | j                         dv rt        }|S | j                         dv rt        }|S | j                         dv rt
        }|S )zd
    Returns the Haystack field type that would likely be associated with each
    Django type.
    )r   r   )r   NullBooleanField)CommaSeparatedIntegerField)r   r   )r   PositiveIntegerFieldPositiveSmallIntegerFieldSmallIntegerField)get_internal_typer   r   r   r   r   )fdefaultresults      rI   index_field_from_django_fieldr     s    
 F >> M 
			"F	F M 
			"A	A  M 
			"@	@ M 
			 # 
 MrO   c                   `     e Zd ZdZ edd      ZeeeddfZ	d fd	Z
d Zd Zd	 Zdd
Z xZS )ModelSearchIndexa)  
    Introspects the model assigned to it and generates a `SearchIndex` based on
    the fields of that model.

    In addition, it adds a `text` field that is the `document=True` field and
    has `use_template=True` option set, just like the `BasicSearchIndex`.

    Usage of this class might result in inferior `SearchIndex` objects, which
    can directly affect your search results. Use this to establish basic
    functionality and move to custom `SearchIndex` objects for better control.

    At this time, it does not handle related fields.
    Tr   contentr   c                 b   t         |           d | _        d | _        g }|xs i | _        t        | dd       | _        | j                  rut        | j                  dd       | _        t        | j                  dg       }t        | j                  dg       }| j                  j                  | j                  ||             | j                  j                         D ]%  \  }}|j                  du s|j                  |       ' t        |      dk(  s"t        d| j                  j                   z        y )Nr'   rw   r$   excludesTrR   rS   )r8   r[   rw   rT   extra_field_kwargsr+   rr   r$   r,   
get_fieldsr.   rW   r0   rX   r   rH   rJ   )rY   r   rZ   r$   r   rB   rE   rH   s          rI   r[   zModelSearchIndex.__init__  s   
!"4":
 T640
:: Wd;DJTZZ26Ftzz:r:H KKtvx@A!%!2!2!4 	2J~~%%%j1	2 >"a'"]..))*  (rO   c                 h    |j                   | j                  v ry|j                  s|j                  ryy)zv
        Given a Django model field, return if it should be included in the
        contributed SearchFields.
        TF)r;   fields_to_skipprimary_keyis_relation)rY   rE   s     rI   should_skip_fieldz"ModelSearchIndex.should_skip_field  s2     ::,,,  1 1rO   c                     | j                   S r   )rw   r^   s    rI   r_   zModelSearchIndex.get_model  s    zzrO   c                     |j                   S )zO
        Given a Django field, return the appropriate index fieldname.
        )r;   )rY   r   s     rI   get_index_fieldnamez$ModelSearchIndex.get_index_fieldname  s     vvrO   c                    i }|xs g }|xs g }| j                   j                  j                  D ]  }|j                  | j                  v r|r|j                  |vr.|r|j                  |v r?| j	                  |      rQt        |      }t        j                  | j                        }|j                  d|j                  i       |j                  du rd|d<   |j                         r|j                  |d<    |di |||j                  <   ||j                     j                  | j                  |              |S )z
        Given any explicit fields to include and fields to exclude, add
        additional fields based on the associated model.
        
model_attrTr   r   rm   )rw   rr   r$   r;   r   r   copyr   r,   r   has_defaultr   r2   r   )rY   r$   r   final_fieldsr   index_field_classr   s          rI   r   zModelSearchIndex.get_fields  s%   
 2>r!!(( 	PAvv$ !&&. AFFh.%%a( =a @YYt667FMM<01vv~!%v}}$%IIy!#4#>v#>L  2243K3KA3NO9	P< rO   r   )NN)rJ   rK   rL   r   r   r   r   r	   r
   r   r[   r   r_   r   r   rM   rN   s   @rI   r   r     s@     d6D)Y	6BN@'rO   r   )/r   	threadingro   django.core.exceptionsr   django.utils.encodingr   haystackr   r   haystack.constantsr   r   r	   r
   r   haystack.fieldsr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   haystack.managerr   haystack.utilsr   r   r    typer"   localr)   r   r   r   rm   rO   rI   <module>r      s       7 + 3 ( F F    & 0 M M9Q4 9Qxo7)//-A o7d	7{ 7 .7 4r{ rrO   