
    h+                         d 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 ddlmZ dd	lmZ  G d
 de      Z G d de      Z G d dej(                  e      Zy)z4
Seamless Polymorphic Inheritance for Django Models
    )ContentType)models)ForwardManyToOneDescriptorReverseOneToOneDescriptor)DEFAULT_DB_ALIAS   )PolymorphicModelBase)PolymorphicManagertranslate_polymorphic_Q_objectc                       e Zd Zy)PolymorphicTypeUndefinedN__name__
__module____qualname__     B/home/dcms/DCMS/lib/python3.12/site-packages/polymorphic/models.pyr   r          r   r   c                       e Zd Zy)PolymorphicTypeInvalidNr   r   r   r   r   r      r   r   r   c                        e Zd ZdZdZdZ ej                  eddej                  d      Z
dgZ e       Z G d d      Zed	        Zefd
Zde_         fdZde_        d Zd Zd Zd Z fdZd Z xZS )PolymorphicModela#  
    Abstract base class that provides polymorphic behaviour
    for any model directly or indirectly derived from it.

    PolymorphicModel declares one field for internal use (:attr:`polymorphic_ctype`)
    and provides a polymorphic manager as the default manager (and as 'objects').
    TFz(polymorphic_%(app_label)s.%(class)s_set+)nulleditable	on_deleterelated_namepolymorphic_ctypec                       e Zd ZdZdZy)PolymorphicModel.MetaTobjectsN)r   r   r   abstractbase_manager_namer   r   r   Metar!   :   s    %r   r%   c                     t        | |      S Nr   )clsqs     r   r   z/PolymorphicModel.translate_polymorphic_Q_object>   s    -c155r   c                     | j                   s6t        j                  j                  |      j	                  | d      | _        yy)z[
        Make sure the ``polymorphic_ctype`` value is correctly set on this model.
        Ffor_concrete_modelN)polymorphic_ctype_idr   r"   
db_managerget_for_modelr   )selfusings     r   pre_save_polymorphicz%PolymorphicModel.pre_save_polymorphicB   sA     ((%0%8%8%C%CE%J%X%X &Y &D" )r   c                     |j                  d| j                  j                  xs t              }| j	                  |       t        |   |i |S )z7Calls :meth:`pre_save_polymorphic` and saves the model.r1   )r1   )get_statedbr   r2   supersave)r0   argskwargsr1   	__class__s       r   r8   zPolymorphicModel.saveR   sF    

7DKKNN$F6FG!!!.w|T,V,,r   c           	      H   | j                   0t        d| j                  j                   d| j                   d      t
        j                  j                  | j                  j                        j                  | j                         j                         }|t        || j                        ss| j                  j                  j                  *t        || j                  j                  j                        s)t        d| j                    d| d| j                   d      |S )z
        Return the actual model type of the object.

        If a non-polymorphic manager (like base_objects) has been used to
        retrieve objects, then the real class/type of these objects may be
        determined using this method.
        z
The model #z does not have a `polymorphic_ctype_id` value defined.
If you created models outside polymorphic, e.g. through an import or migration, make sure the `polymorphic_ctype_id` field points to the ContentType ID of the model subclass.zContentType z for z #z does not point to a subclass!)r-   r   r;   r   pkr   r"   r.   r5   r6   
get_for_idmodel_class
issubclass_metaproxy_for_modelr   )r0   models     r   get_real_instance_classz(PolymorphicModel.get_real_instance_classZ   s     $$,*T^^445Qtwwi @q r  **4;;>>:Z112[] 	 udnn5$$44<!%)=)=)M)MN )t889ugRyPno  r   c                     | j                         }|y t        j                  j                  | j                  j
                        j                  |d      j                  S NTr+   )rE   r   r"   r.   r5   r6   r/   r>   r0   r@   s     r   #get_real_concrete_instance_class_idz4PolymorphicModel.get_real_concrete_instance_class_id   sM    224**4;;>>:];4]@R	
r   c                     | j                         }|y t        j                  j                  | j                  j
                        j                  |d      j                         S rG   )rE   r   r"   r.   r5   r6   r/   r@   rH   s     r    get_real_concrete_instance_classz1PolymorphicModel.get_real_concrete_instance_class   sO    224**4;;>>:];4]@[]	
r   c                     | j                         }|| j                  k(  r| S |j                  j                  | j                  j
                        j                  | j                        S )a  
        Upcast an object to it's actual type.

        If a non-polymorphic manager (like base_objects) has been used to
        retrieve objects, then the complete object with it's real class/type
        and all fields may be retrieved with this method.

        .. note::
            Each method call executes one db query (if necessary).
            Use the :meth:`~polymorphic.managers.PolymorphicQuerySet.get_real_instances`
            to upcast a complete list in a single efficient query.
        r>   )rE   r;   r"   r.   r5   r6   r4   r>   )r0   
real_models     r   get_real_instancez"PolymorphicModel.get_real_instance   sT     113
'K!!,,T[[^^<@@DGG@LLr   c                    t        |   |i | | j                  j                  ryd| j                  _        d }| j	                         }|j                         D ]c  \  }}t        | j                  |d      }t        t        |      t        t        f      s=t        | j                  |t         |||                   e y)aK  Replace Django's inheritance accessor member functions for our model
        (self.__class__) with our own versions.
        We monkey patch them until a patch can be added to Django
        (which would probably be very small and make all of this obsolete).

        If we have inheritance of the form ModelA -> ModelB ->ModelC then
        Django creates accessors like this:
        - ModelA: modelb
        - ModelB: modela_ptr, modelb, modelc
        - ModelC: modela_ptr, modelb, modelb_ptr, modelc

        These accessors allow Django (and everyone else) to travel up and down
        the inheritance tree for the db object at hand.

        The original Django accessors use our polymorphic manager.
        But they should not. So we replace them with our own accessors that use
        our appropriate base_objects manager.
        NTc                       fd}|S )Nc                 n    t        dj                        }|j                  | j                        }|S )N_base_objectsrM   )getattrr"   r4   r>   )r0   r"   attrrD   s      r   accessor_functionz`PolymorphicModel.__init__.<locals>.create_accessor_function_for_model.<locals>.accessor_function   s.    !%%--H{{dgg{.r   r   )rD   accessor_namerV   s   `  r   "create_accessor_function_for_modelzEPolymorphicModel.__init__.<locals>.create_accessor_function_for_model   s    
 %$r   )r7   __init__r;   (polymorphic_super_sub_accessors_replaced+_get_inheritance_relation_fields_and_modelsitemsrT   rA   typer   r   setattrproperty)	r0   r9   r:   rX   %subclasses_and_superclasses_accessorsnamerD   orig_accessorr;   s	           r   rY   zPolymorphicModel.__init__   s    & 	$)&)>>BBBF?	% 150`0`0b-@FFH 	KD%#DNND$?M]#*,FG NN?tLM	r   c                      d  fdfdfd}i }  j                   |        | j                   |       |S )zxhelper function for __init__:
        determine names of all Django inheritance accessor member functions for type(self)c                     | ||<   y r'   r   )rD   
field_nameresults      r   	add_modelzOPolymorphicModel._get_inheritance_relation_fields_and_models.<locals>.add_model   s    !&F:r   c                     t        | t        j                        r9| t        j                  k7  r%| j                  k7  r| t        k7  r | ||       y y y y y r'   )rA   r   Modelr;   r   )rD   re   rf   rg   r0   s      r   add_model_if_regularzZPolymorphicModel._get_inheritance_relation_fields_and_models.<locals>.add_model_if_regular   sR    5&,,/V\\)T^^+--%V4 . , * 0r   c                     | j                   j                  j                         D ]'  \  }}|	|j                  } |||        ||       ) y r'   )rB   parentsr\   ra   )rD   rf   	super_clsfield_to_superre   add_all_super_modelsrj   s        r   ro   zZPolymorphicModel._get_inheritance_relation_fields_and_models.<locals>.add_all_super_models   sS    -2[[-@-@-F-F-H <)	>!- "0!4!4J(JG(F;<r   c                 ,   | j                         D ]  }| |j                  j                  v s|j                  j                  |    }|8|j                  }|j                  |j
                  j                         }n|j                  } |||        y r'   )__subclasses__rB   rl   remote_fieldr   r   lower)rm   rf   sub_clsrn   super_to_sub_related_fieldto_subclass_fieldnamerj   s         r   add_all_sub_modelszXPolymorphicModel._get_inheritance_relation_fields_and_models.<locals>.add_all_sub_models   s    $335 U 5 55%,]]%:%:9%EN%15C5P5P25BBJ4;4D4D4J4J4L1 5O4[4[1,W6KVTUr   r;   )r0   rw   rf   ro   rg   rj   s   `  @@@r   r[   z<PolymorphicModel._get_inheritance_relation_fields_and_models   s@    	'	5	<	U& T^^V44>>62r   )r   r   r   __doc__polymorphic_model_marker"polymorphic_query_multiline_outputr   
ForeignKeyr   CASCADEr   !polymorphic_internal_model_fieldsr
   r"   r%   classmethodr   r   r2   alters_datar8   rE   rI   rK   rO   rY   r[   __classcell__rx   s   @r   r   r      s      $ */& *))..? *=(=% !"G& & 6 6 *:  (,$- D(T

M$.`0r   r   )	metaclassN)ry   "django.contrib.contenttypes.modelsr   	django.dbr   django.db.models.fields.relatedr   r   django.db.utilsr   baser	   managersr
   query_translater   LookupErrorr   RuntimeErrorr   ri   r   r   r   r   <module>r      sN    ;  a , & ( ;	{ 		\ 	pv||/C pr   