a
    CgT                     @   s   d dl mZ d dlmZ d dlmZ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 d d	lmZ d
d ZG dd deZG dd deZdd ZG dd deZG dd deZdS )    )unicode_literals)checks)IntegrityErrorconnectionsrouter)CASCADE)
ForeignKeyManyToManyField)cached_property)ReverseManyToOneDescriptorManyToManyDescriptor)sort_by_fields)FakeQuerySetc                    s<     jjjj}G  fddd|}|S )aG  
    Create a DeferringRelatedManager class that wraps an ordinary RelatedManager
    with 'deferring' behaviour: any updates to the object set (via e.g. add() or clear())
    are written to a holding area rather than committed to the database immediately.
    Writing to the database is deferred until the model is saved.
    c                       s   e Zd Z fddZefddZdd Zdd Zfd	d
ZfddZ	dd Z
d" fdd	ZfddZfddZdd ZfddZdd Zd#fdd	Zfd d!Z  ZS )$zIcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManagerc                    s   t    | _|| _d S N)super__init__modelinstanceselfr   )	__class__	rel_model R/var/www/lab.imftr.de/x/nb_venv/lib/python3.9/site-packages/modelcluster/fields.pyr      s    
zRcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.__init__c                    s    t | jdi v S )N_cluster_related_objects)getattrr   r   relation_namer   r   is_deferring$   s    zVcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.is_deferringc                 S   s2   z
| j jW S  ty,   i }|| j _| Y S 0 d S r   r   r   AttributeErrorr   cluster_related_objectsr   r   r   _get_cluster_related_objects*   s    
zfcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager._get_cluster_related_objectsc                 S   s   |   S r   )get_live_querysetr   r   r   r   get_live_query_set4   s    z\create_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.get_live_query_setc                    s    | j  S zb
            return the original manager's queryset, which reflects the live database
            )r   get_querysetr   original_manager_clsr   r   r%   9   s    z[create_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.get_live_querysetc              	      sR   z| j j }W n4 ttfyD   | j jdu r4g }n|   Y S Y n0 t j|S )
            return the current object set with any updates applied,
            wrapped up in a FakeQuerySet if it doesn't match the database state
            N)r   r   r!   KeyErrorpkr%   r   related_modelr   results)relatedr   r   r   r(   ?   s    zVcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.get_querysetc                 S   s   |   S r   )_next_is_stickyallr   querysetr   r   r   _apply_rel_filtersO   s    z\create_deferring_foreign_related_manager.<locals>.DeferringRelatedManager._apply_rel_filtersNc                    s   |d u r2| j p tj| j|d d}t  |}j}j t	 fdd|D }dj
 |i}|jf i |}|D ]}||| }	t|j
|	 qv }
|| d|
dfS )Nr   r   c                 3   s   | ]} ||fV  qd S r   r   ).0instZinstance_attrr   r   	<genexpr>^       zrcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.get_prefetch_queryset.<locals>.<genexpr>%s__inF)_dbr   Zdb_for_readr   r   r(   usingZget_local_related_valueZget_foreign_related_valuedictnamefiltersetattrrelated_query_name)r   	instancesr5   dbZrel_obj_attrZinstances_dictqueryqsZrel_objr   Z
cache_name)r   	rel_fieldr:   r   get_prefetch_querysetW   s    z_create_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.get_prefetch_querysetc                    sR   |   }z|  }W n8 tyL   | jjdu r4g }nt|  }|| < Y n0 |S ),  
            return the mutable list that forms the current in-memory state of
            this relation. If there is no such list (i.e. the manager is returning
            querysets from the live database instead), one is created, populating it
            with the live database state
            N)r$   r,   r   r-   listr%   r   r#   Zobject_listr   r   r   get_object_listj   s    zYcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.get_object_listc                    s   |   }|D ]R}d}t|D ] \}}||kr|||< d} q>q|sL|| t|jj| j q jjrt	|dkrt
| jj dS ){
            Add the passed items to the stored object set, but do not commit them
            to the database
            FT   N)rN   	enumerateappendrC   fieldrA   r   _metaorderinglenr   r   Z	new_itemsitemstargetZitem_matchediitem)r   r1   r   r   add~   s    
zMcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.addc                    s&   |   } fdd|D |dd< dS )
            Remove the passed items from the stored object set, but do not commit the change
            to the database
            c                    s   g | ]}| vr|qS r   r   r8   r[   items_to_remover   r   
<listcomp>   r<   zdcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.remove.<locals>.<listcomp>NrN   r   r`   rX   r   r_   r   remove   s    zPcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.removec                    s&   |   } jf i |}|| |S r   )rN   r.   rR   )r   kwargsrX   Znew_item)r1   r   r   create   s    
zPcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.createc                 S   s   |  g  dS zU
            Clear the stored object set, without affecting the database
            Nsetr   r   r   r   clear   s    zOcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.clearTFc                    sZ   t |}|  }|D ]}t|jj| j q jjrNt|dkrNt	| jj ||< d S )NrP   )
rL   r$   rC   rS   rA   r   rT   rU   rV   r   )r   objsbulkrj   r#   obj)r   r1   r   r   r   ri      s    zMcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.setc              	      s   | j jdu rtd z| j j }W n ttfy@   Y dS 0  | j }t| }|D ]}||vr\|  q\|D ]}|j	|dd qv| j j= dS )z
            Apply any changes made to the stored object set to the database.
            Any objects removed from the initial set will be deleted entirely
            from the database.
            N-Cannot commit relation %r on an unsaved modelF)rl   )
r   r-   r   r   r!   r,   rL   r(   deleter\   )r   final_itemsoriginal_manager
live_itemsr[   )r*   r   r   r   commit   s    

zPcreate_deferring_foreign_related_manager.<locals>.DeferringRelatedManager.commit)N)TF)__name__
__module____qualname__r   propertyr   r$   r&   r%   r(   r6   rJ   rN   r\   rd   rf   rj   ri   rs   __classcell__r   r*   rI   r   r1   r   r   r   DeferringRelatedManager   s    

r{   )get_accessor_namerS   r.   _default_managerr   )r1   r*   
superclassr{   r   ry   r   (create_deferring_foreign_related_manager   s     Gr   c                   @   s*   e Zd ZdddZdd Zedd ZdS )	ChildObjectsDescriptorNc                 C   s   |d u r| S |  |S r   child_object_manager_clsr   r   Zinstance_typer   r   r   __get__   s    zChildObjectsDescriptor.__get__c                 C   s   |  |}|| d S r   r   ri   r   r   valuemanagerr   r   r   __set__   s    
zChildObjectsDescriptor.__set__c                 C   s   t | j| jS r   )r   relrelated_manager_clsr   r   r   r   r      s    z/ChildObjectsDescriptor.child_object_manager_cls)Nrt   ru   rv   r   r   r
   r   r   r   r   r   r      s   
r   c                       s,   e Zd ZeZ fddZ fddZ  ZS )ParentalKeyc                    s"   | dt t j|i | d S )NZ	on_delete)
setdefaultr   r   r   )r   argsre   rz   r   r   r      s    zParentalKey.__init__c                    s   ddl m} t jf i |}t| jjtrpt| jj|sp|	t
jddj| jjjjd | jjj d| dd | j d	kr|	t
jd
d| dd |S )Nr   )ClusterableModelz9ParentalKey must point to a subclass of ClusterableModel.zHChange {model_name} into a ClusterableModel or use a ForeignKey instead..)Z
model_namezmodelcluster.E001)hintrm   id+z5related_name='+' is not allowed on ParentalKey fieldsz-Either change it to a valid name or remove itzmodelcluster.E002)Zmodelcluster.modelsr   r   check
isinstanceremote_fieldr   type
issubclassrR   r   ErrorformatrT   Z	app_labelrt   r|   )r   re   r   errorsrz   r   r   r      s.    	zParentalKey.check)rt   ru   rv   r   related_accessor_classr   r   rx   r   r   rz   r   r      s   r   c                    sR   | j }|j| | | jjj}| jG  fddd|}|S )Nc                       s   e Zd Zd fdd	ZfddZdd Zdd	 Zfd
dZd fdd	Zdd Z	fddZ
fddZdd Zd fdd	Zdd ZfddZ  ZS )!zRcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManagerNc                    s    t    | _| _|| _d S r   )r   r   r   throughr   r   )r   r   rel_throughr   r   r   +  s    
z[create_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.__init__c                    s
    | j S r   r7   r   r)   r   r   get_original_manager1  s    zgcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.get_original_managerc                 S   s   |    S r'   )r   r(   r   r   r   r   r%   4  s    zdcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.get_live_querysetc                 S   s2   z
| j jW S  ty,   i }|| j _| Y S 0 d S r   r    r"   r   r   r   r$   :  s    
zocreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager._get_cluster_related_objectsc              	      sT   z| j j }W n8 ttfyH   | j jr6|   Y S  j  Y S Y n0 t |S )r+   )	r   r   r!   r,   r-   r%   Zobjectsnoner   r/   r   r   r   r   r(   D  s    z_create_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.get_querysetc                    s   |d u rt   }|j|d d ||jp0| j}d |i}| jf i |}| jj	j
jjt|j   jj|jfddjD d}|fdd fd	dd
d
fS )Nr   r7   r=   c                    s*   i | ]"}d |j  d |jf qS )_prefetch_related_val_%sz%s.%s)attnamecolumnr8   f)
join_tableqnr   r   
<dictcomp>f  s   z|create_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.get_prefetch_queryset.<locals>.<dictcomp>)selectc                    s   t  fddjD S )Nc                 3   s   | ]}t  d |j V  qdS )r   N)r   r   r   resultr   r   r;   l  s   create_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.get_prefetch_queryset.<locals>.<lambda>.<locals>.<genexpr>)tuplelocal_related_fieldsr   )fkr   r   <lambda>l  s   zzcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.get_prefetch_queryset.<locals>.<lambda>c                    s   t  fddjD S )Nc                 3   s"   | ]}| t|j V  qd S r   )Zget_db_prep_valuer   r   r   )
connectionr9   r   r   r;   p  s   r   )r   Zforeign_related_fieldsr9   )r   r   r   r   r   p  s   F)r   r(   Z
_add_hintsr?   r>   r2   rB   r   rT   	get_fieldr   Zdb_tabler   rF   opsZ
quote_nameextrar   )r   rE   r5   rG   )r   query_field_namer   source_field_name)r   r   r   r   r   rJ   U  s(    




zhcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.get_prefetch_querysetc                 S   s   |  S r   )r2   r4   r   r   r   r6   y  s    zecreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager._apply_rel_filtersc                    s@   |   }z|  }W n& ty:   t|  }|| < Y n0 |S )rK   )r$   r,   rL   r%   rM   r   r   r   rN   }  s    zbcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.get_object_listc                    s   |   }|D ]V}|jdu r&td| d}t|D ] \}}||kr2|||< d} qTq2|s|| q jjrt|dkrt| jj dS )rO   Nzb"%r" needs to have a primary key value before it can be added to a parental many-to-many relation.FTrP   )	rN   r-   
ValueErrorrQ   rR   rT   rU   rV   r   rW   )r   r   r   r\     s     
zVcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.addc                 S   s   |  g  dS rg   rh   r   r   r   r   rj     s    zXcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.clearTFc                    sf   t |}|r0t|d  s0|  }|| d S |  } jjrZt|dkrZt| jj ||< d S )Nr   rP   )	rL   r   r   ri   r$   rT   rU   rV   r   )r   rk   rl   rj   rq   r#   r   r   r   ri     s    
zVcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.setc                    s&   |   } fdd|D |dd< dS )r]   c                    s   g | ]}| vr|qS r   r   r^   r_   r   r   ra     r<   zmcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.remove.<locals>.<listcomp>Nrb   rc   r   r_   r   rd     s    zYcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.removec              	      s   | j jstd z| j j  W n ttfy<   Y dS 0 |  }t|  fddD }fdd D }|r|j	|  |r|j
|  | j j= dS )zZ
            Apply any changes made to the stored object set to the database.
            rn   Nc                    s   g | ]}| vr|qS r   r   r^   )rp   r   r   ra     r<   zmcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.commit.<locals>.<listcomp>c                    s   g | ]}| vr|qS r   r   r^   )rr   r   r   ra     r<   )r   r-   r   r   r!   r,   r   rL   r(   rd   r\   )r   rq   r`   Zitems_to_addr   )rp   rr   r   rs     s    

zYcreate_deferring_forward_many_to_many_manager.<locals>.DeferringManyRelatedManager.commit)N)N)TF)rt   ru   rv   r   r   r%   r$   r(   rJ   r6   rN   r\   rj   ri   rd   rs   rx   r   r*   r   r   r   r   r   rz   r   DeferringManyRelatedManager*  s   
$
r   )rS   rA   rD   Zm2m_field_namer   r}   r   r   )r   r*   rI   r~   r   r   r   r   -create_deferring_forward_many_to_many_manager!  s     Br   c                   @   s*   e Zd ZdddZdd Zedd ZdS )	ParentalManyToManyDescriptorNc                 C   s   |d u r| S |  |S r   r   r   r   r   r   r     s    z$ParentalManyToManyDescriptor.__get__c                 C   s   |  |}|| d S r   r   r   r   r   r   r     s    
z$ParentalManyToManyDescriptor.__set__c                 C   s   | j }t|| jS r   )r   r   r   )r   r   r   r   r   r     s    z5ParentalManyToManyDescriptor.child_object_manager_cls)Nr   r   r   r   r   r     s   
r   c                       s,   e Zd ZeZdZ fddZdd Z  ZS )ParentalManyToManyFieldTc                    s0   t  j||fi | t|| j| | j d S r   )r   contribute_to_classrC   rA   r   r   )r   clsrA   re   rz   r   r   r     s    z+ParentalManyToManyField.contribute_to_classc                 C   s   t || j S r   )r   r   r3   )r   rm   r   r   r   value_from_object  s    z)ParentalManyToManyField.value_from_object)	rt   ru   rv   r   r   Z_need_commit_after_assignmentr   r   rx   r   r   rz   r   r      s   	r   N)
__future__r   Zdjango.corer   Z	django.dbr   r   r   Zdjango.db.modelsr   Zdjango.db.models.fields.relatedr   r	   Zdjango.utils.functionalr
   r   r   Zmodelcluster.utilsr   Zmodelcluster.querysetr   r   r   r   r   r   r   r   r   r   r   <module>   s     W* N