a
    8XhP%                     @   sp   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 Z
dd	 Zd
d Zdd ZG dd deZdS )    )apps)GenericForeignKey)BaseCommand)transaction)signalcommandc                  C   sL   t  } d}| D ]}td||jf  |d7 }qttd}| |d  }|S )N   %s. %sz=Enter the number of the model you would like to de-duplicate:)r   
get_modelsprint__name__intinput)modelsiteratormodelZmodel_choiceZmodel_to_deduplicate r   /var/www/viveiro_mudafortebrasil/venv/lib/python3.9/site-packages/django_extensions/management/commands/merge_model_instances.pyget_model_to_deduplicate
   s    
r   c           	         sN  dd | j  D }d}|D ]}td||f  |d7 }qd}|slttd}|td|v rbd}q>td q>||d  g d}|sJ fd	d|D }d}|D ]}td||f  |d7 }qtd
 d}|s~td td d  td}|dkrd}d}qt|ttdt|d v r> |t|d  g7  d}qtd qq~ S )Nc                 S   s   g | ]
}|j qS r   )name).0fieldr   r   r   
<listcomp>       z#get_field_names.<locals>.<listcomp>r   r   FzEEnter the number of the (first) field you would like to de-duplicate.Tz Invalid input. Please try again.c                    s   g | ]}| vr|qS r   r   )r   fZfields_to_deduplicater   r   r   &   s   zC. Done adding fields.z8You are currently deduplicating on the following fields:
z
                Enter the number of the field you would like to de-duplicate.
                If you have entered all fields, enter C to continue.
            C)	_meta
get_fieldsr
   r   r   rangejoinlistlen)	r   fieldsr   r   Z	validatedZfirst_fielddoneZavailable_fieldsZadditional_fieldr   r   r   get_field_names   sF    




 r%   c                  C   s   t d} | dv r | S q d S )Nz
            Do you want to keep the first or last duplicate instance?
            Enter "first" or "last" to continue.
            )firstlast)r   )first_or_lastr   r   r   keep_first_or_last_instanceD   s    r)   c                  C   s>   g } t  D ],}|j D ]\}}t|tr| | qq| S )z6Return a list of all GenericForeignKeys in all models.)r   r	   __dict__items
isinstancer   append)generic_fieldsr   
field_namer   r   r   r   get_generic_fieldsN   s    
r0   c                   @   s,   e Zd ZdZedd Ze dd ZdS )Commanda  
        Removes duplicate model instances based on a specified
        model and field name(s).

        Makes sure that any OneToOne, ForeignKey, or ManyToMany relationships
        attached to a deleted model(s) get reattached to the remaining model.

        Based on the following:
        https://djangosnippets.org/snippets/2283/
        https://stackoverflow.com/a/41291137/2532070
        https://gist.github.com/edelvalle/01886b6f79ba0c4dce66
    c              	   O   s   t  }t|}t }d}|j D ]}i }|D ]}	||	}
||	|
i q.z|jjf i | W q" |jy   |jj	f i |}|dkr|
 }|j|jd}n|dkr| }|j|jd}| ||\}}}||7 }Y q"0 q"td| d S )Nr   r&   )pkr'   z(Successfully deleted {} model instances.)r   r%   r)   objectsall__getattribute__updategetZMultipleObjectsReturnedfilterr&   excluder2   r'   merge_model_instancesr
   format)selfargsoptionsr   field_namesr(   Ztotal_deleted_objects_countinstancekwargsr/   Zinstance_field_valueZ	instancesprimary_objectalias_objectsdeleted_objectsdeleted_objects_countr   r   r   handlef   s0    
zCommand.handlec                 C   st  t  }ttdd |j }ttdd |}ttdd |}g }d}|D ]}|D ]}	|	j}
t||
}| D ]}z$t||
| t||
	| W qt t
y   t||
j}|	 ||	 |i}|jjf i |}|D ]}t||	 | |  qY qt0 qtqX|D ]}|jrZ| }
t||
}| D ]"}|jj}t||| |  q4np|jsj|jr|j}
t||
}t||
}|du rt||
| |  n&|jr| jd||j |  q|D ]^}i }| ||j< ||||j< |jjjf i |}|D ]}t||j| |  qq|jrN||g7 }| jd||j |  |d7 }qN|||fS )	z
        Merge several model instances into one, the `primary_object`.
        Use this function to merge model objects and migrate all of the related
        fields from the alias objects the primary object.
        c                 S   s
   | j du S NT)Zis_relationxr   r   r   <lambda>   r   z/Command.merge_model_instances.<locals>.<lambda>c                 S   s
   | j du S rG   Zmany_to_manyrH   r   r   r   rJ      r   c                 S   s
   | j du S )NFrK   rH   r   r   r   rJ      r   r   NzDeleted {} with id {}
r   ) r0   r!   r8   r   r   r   getattrr4   removeaddAttributeErrorZthroughZm2m_reverse_field_nameZm2m_field_namer3   setattrsaveZone_to_manyZget_accessor_namer   Z
one_to_oneZmany_to_onestdoutwriter;   iddeleteZ_get_pk_valZfk_fieldget_content_typeZct_fieldr   )r<   rB   rC   r.   Zrelated_fieldsZmany_to_many_fieldsrD   rE   Zalias_objectZmany_to_many_fieldZalias_varnameZrelated_objectsobjZthrough_modelrA   Zthrough_model_instancesr@   Zrelated_fieldr/   Zrelated_objectZprimary_related_objectr   Zfilter_kwargsZgeneric_related_objectr   r   r   r:      s    










zCommand.merge_model_instancesN)	r   
__module____qualname__helpr   rF   r   Zatomicr:   r   r   r   r   r1   X   s
   
r1   N)Zdjango.appsr   Z"django.contrib.contenttypes.fieldsr   Zdjango.core.managementr   Z	django.dbr   Z"django_extensions.management.utilsr   r   r%   r)   r0   r1   r   r   r   r   <module>   s   /

