a
    CgvA                     @   s   d dl mZ 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 d dlmZ d dlmZ d d	lmZ d d
lmZmZ dd Zdd ZdddZdd Zdd ZG dd dejZdS )    )unicode_literalsN)FieldDoesNotExist)modelstransaction)ForeignObjectRel)is_protected_type)DjangoJSONEncoder)settings)timezone)ParentalKeyParentalManyToManyFieldc                 C   s   | j d u r| j||jd u d}t|tjrjtjrjt|rZt	 }t
||tjj}nt|tjj}t|rv|S | |S nt||  S d S )N)add)remote_fieldZpre_savepk
isinstancedatetimer	   USE_TZr
   Zis_naiveget_default_timezone
make_aware
astimezoneutc	localtimer   Zvalue_to_stringgetattrZget_attname)fieldmodelvaluedefault_timezone r   R/var/www/lab.imftr.de/x/nb_venv/lib/python3.9/site-packages/modelcluster/models.pyget_field_value   s    

r   c                 C   sZ   | j j}|jr$|jjr$|jjj j}qdt|| i}| j jD ]}|jr:t|| ||j< q:|S )z
    Return a serialised version of the model's fields which exist as local database
    columns (i.e. excluding m2m and incoming foreign key relations)
    r   )	_metar   r   parent_linkr   r   fields	serializename)r   pk_fieldobjr   r   r   r    get_serializable_data_for_fields'   s    r'   TFc              	   C   sB  | j j}i }|jr6|jjr6|d ||j< |jjj j}q|d ||j< | D ]\}}z| j |}W n ty|   Y qLY n0 t	|t
rqL|jrt	|jtjr|jjjj|d}	t|	||j< qL|jrt	|jtjr|d u rd ||j< n|jjj |jj|}
|
||j< |rz"|jjjjf i |jj|
i W nz |jjjy   |jjtjkr`nN|jjtjkr|r~Y  d S d ||j< n$|jjtjkrd ||j< ntdY n0 qL||}t	|tjrtjr|d urt }t|rt ||}nt!||}|||j"< qL| f i |}|d d ur>d|j#_$|S )Nr   )Zpk__inzRcan't currently handle on_delete types other than CASCADE, SET_NULL and DO_NOTHINGF)%r    r   r   r!   attnamer   items	get_fieldr   r   r   r   ZManyToManyRelZ_default_managerfilterlistZManyToOneRel
field_nameZ	to_pythongetZDoesNotExistZ	on_deleteZ
DO_NOTHINGZCASCADEZSET_NULL	ExceptionZDateTimeFieldr	   r   r
   r   Zis_awarer   r   r$   _stateZadding)r   data	check_fks
strict_fksr%   kwargsr-   Zfield_valuer   Zrelated_objectsZclean_valuer   r   r&   r   r   r   model_from_serializable_data:   sZ    


"
 r5   c                 C   s   dd | j  D S )z
    Return a list of RelatedObject records for child relations of the given model,
    including ones attached to ancestors of the model
    c                 S   s   g | ]}t |jtr|qS r   )r   r   r   .0r   r   r   r   
<listcomp>   s   z+get_all_child_relations.<locals>.<listcomp>r    
get_fieldsr   r   r   r   get_all_child_relations   s    r<   c                 C   s   dd | j  D S )z}
    Return a list of ParentalManyToManyFields on the given model,
    including ones attached to ancestors of the model
    c                 S   s   g | ]}t |tr|qS r   )r   r   r6   r   r   r   r8      s   
z/get_all_child_m2m_relations.<locals>.<listcomp>r9   r;   r   r   r   get_all_child_m2m_relations   s    r=   c                       s   e Zd Z fddZ fddZdd Zdd ZedddZedddZ	e
jdddZdddZdddZG dd dZ  ZS )ClusterableModelc           	         s   dd t | D dd t| D  }t fdd|D r  }i }|D ]}| v rJ||||< qJt j|i | | D ]\}}t| || qnt j|i   dS )zv
        Extend the standard model constructor to allow child object lists to be passed in
        via kwargs
        c                 S   s   g | ]}|  qS r   get_accessor_namer7   relr   r   r   r8          z-ClusterableModel.__init__.<locals>.<listcomp>c                 S   s   g | ]
}|j qS r   r$   r6   r   r   r   r8      rC   c                 3   s   | ]}| v V  qd S Nr   )r7   r$   r4   r   r   	<genexpr>   rC   z,ClusterableModel.__init__.<locals>.<genexpr>N)	r<   r=   anycopypopsuper__init__r)   setattr)	selfargsr4   child_relation_namesZkwargs_for_superZrelation_assignmentsrel_namer-   Zrelated_instances	__class__rF   r   rL      s    zClusterableModel.__init__c           
         s   dd t | D }dd t| D }|dd}|du rFd}|}|}nHg }g }g }|D ]6}||v rn|| qV||v r|| qV|| qVt jf d|i| |D ]}	t| |	  q|D ]}t| |  qdS )z@
        Save the model and commit all child relations.
        c                 S   s   g | ]}|  qS r   r?   rA   r   r   r   r8      rC   z)ClusterableModel.save.<locals>.<listcomp>c                 S   s   g | ]
}|j qS r   rD   r6   r   r   r   r8      rC   update_fieldsN)r<   r=   rJ   appendrK   saver   commit)
rN   r4   rP   Zchild_m2m_field_namesrT   Zreal_update_fieldsZrelations_to_commitZm2m_fields_to_commitr   ZrelationrR   r   r   rV      s*    zClusterableModel.savec                 C   s   t | }t| D ]L}| }t| | }t|jdrJdd |D ||< qdd |D ||< qt| D ].}|jrft| |j	 }dd |D ||j	< qf|S )Nserializable_datac                 S   s   g | ]}|  qS r   )rX   r7   childr   r   r   r8      rC   z6ClusterableModel.serializable_data.<locals>.<listcomp>c                 S   s   g | ]}t |qS r   )r'   rY   r   r   r   r8      rC   c                 S   s   g | ]
}|j qS r   )r   rY   r   r   r   r8      rC   )
r'   r<   r@   r   allhasattrrelated_modelr=   r#   r$   )rN   r&   rB   rQ   childrenr   r   r   r   rX      s    z"ClusterableModel.serializable_datac                 C   s   t j|  tdS )N)cls)jsondumpsrX   r   )rN   r   r   r   to_json   s    zClusterableModel.to_jsonTFc           
   	      s   t | | |d}|du rdS t| }|D ]}| }z|| }W n tyV   Y q(Y n0 |jtdr~ fdd|D }	n fdd|D }	tdd |	}	t|||	 q(|S )	a  
        Build an instance of this model from the JSON-like structure passed in,
        recursing into related objects as required.
        If check_fks is true, it will check whether referenced foreign keys still
        exist in the database.
        - dangling foreign keys on related objects are dealt with by either nullifying the key or
        dropping the related object, according to the 'on_delete' setting.
        - dangling foreign keys on the base object will be nullified, unless strict_fks is true,
        in which case any dangling foreign keys with on_delete=CASCADE will cause None to be
        returned for the entire object.
        r2   r3   Nfrom_serializable_datac                    s   g | ]}j | d dqS Trc   )rd   r7   Z
child_datar2   r]   r   r   r8     s   z;ClusterableModel.from_serializable_data.<locals>.<listcomp>c                    s   g | ]}t | d dqS re   )r5   rf   rg   r   r   r8   	  s   c                 S   s   | d uS rE   r   )rZ   r   r   r   <lambda>  rC   z9ClusterableModel.from_serializable_data.<locals>.<lambda>)r5   r<   r@   KeyErrorr]   r\   r+   rM   )
r_   r1   r2   r3   r&   Zchild_relationsrB   rQ   Zchild_data_listr^   r   rg   r   rd      s*    

z'ClusterableModel.from_serializable_datac                 C   s   | j t|||dS )Nrc   )rd   r`   loads)r_   Z	json_datar2   r3   r   r   r   	from_json  s    zClusterableModel.from_jsonc                 C   s   i }t |tr| j|}t |jts.td|jj}t	| |
 }t	||
 }|s^|  | dD ]p}	|	j}
|
du}d|	_t|	||j ||	 |
dur|	|||
f< ql|df|vrg ||df< ||df |	 ql|r|  |S )a[  
        Copies all of the objects in the accessor_name to the target object.

        For example, say we have an event with speakers (my_event) and we need to copy these to another event (my_other_event):

            my_event.copy_child_relation('speakers', my_other_event)

        By default, this copies the child objects without saving them. Set the commit paremter to True to save the objects
        but note that this would cause an exception if the target object is not saved.

        This will overwrite the child relation on the target object. This is to avoid any issues with unique keys
        and/or sort_order. If you want it to append. set the `append` parameter to True.

        This method returns a dictionary mapping the child relation/primary key on the source object to the new object created for the
        target object.
        zQcopy_child_relation can only be used for relationships defined with a ParentalKeyr   N)r   strr    r*   r   r   LookupErrorr   r(   r   r@   clearr[   Zorder_byr   rM   idr   rU   rW   )rN   child_relationtargetrW   rU   child_object_mapZparental_key_nameZsource_managerZtarget_managerZchild_objectZold_pkZis_savedr   r   r   copy_child_relation  s0    

z$ClusterableModel.copy_child_relationNc              	   C   sD   |pg }i }t | D ]*}| |v r&q|| j||||d q|S )a  
        Copies all of the objects in all child relations to the target object.

        This will overwrite all of the child relations on the target object.

        Set exclude to a list of child relation accessor names that shouldn't be copied.

        This method returns a dictionary mapping the child_relation/primary key on the source object to the new object created for the
        target object.
        )rW   rU   )r<   r@   updaters   )rN   rq   excluderW   rU   rr   rp   r   r   r   copy_all_child_relationsS  s    z)ClusterableModel.copy_all_child_relationsc                 C   s   |pg }i }| j  D ]}|j|v r&q|jr.q|jrlt|trt| |j}t|dr|	 }|r|||j< qt|t
jr|jjrqt|t
jrd||j< t| |j||j< qt| |j||j< q| jf i |}| j||d}||fS )a  
        Makes a copy of this object and all child relations.

        Includes all field data including child relations and parental many to many fields.

        Doesn't include non-parental many to many.

        The result of this method is unsaved.
        r[   N)ru   )r    r:   r$   Zauto_createdZmany_to_manyr   r   r   r\   r[   r   ZOneToOneFieldr   r!   Z
ForeignKeyr(   rS   rv   )rN   Zexclude_fieldsZ	data_dictr   Zparental_fieldvaluesrI   rr   r   r   r   copy_clusteri  s0    





zClusterableModel.copy_clusterc                   @   s   e Zd ZdZdS )zClusterableModel.MetaTN)__name__
__module____qualname__Zabstractr   r   r   r   Meta  s   r|   )TF)TF)FF)NFF)N)ry   rz   r{   rL   rV   rX   rb   classmethodrd   rk   r   Zatomicrs   rv   rx   r|   __classcell__r   r   rR   r   r>      s    +:

;r>   )TF)
__future__r   r`   r   Zdjango.core.exceptionsr   Z	django.dbr   r   Zdjango.db.models.fields.relatedr   Zdjango.utils.encodingr   Zdjango.core.serializers.jsonr   Zdjango.confr	   Zdjango.utilsr
   Zmodelcluster.fieldsr   r   r   r'   r5   r<   r=   ZModelr>   r   r   r   r   <module>   s    
H