o
    i1&                     @   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modelmodel_choicemodel_to_deduplicate r   {/var/www/html/formularioweb/env/lib/python3.10/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}|s7ttd}|td|v r1d}ntd |r!||d  g d}|s fd	d|D }d}|D ]}td||f  |d7 }qOtd
 d}|std td d  td}|dkrd}d}n!t|ttdt|d v r |t|d  g7  d}ntd |rf|rB S )Nc                 S   s   g | ]}|j qS r   )name).0fieldr   r   r   
<listcomp>   s    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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   	validatedfirst_fielddoneavailable_fieldsadditional_fieldr   r   r   get_field_names   sP   


r+   c                  C   s   	 t d} | dv r| S q)NTz
            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_instanceH   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_fieldsR   s   

r6   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di | W q |jyp   |jj	di |}|dkrR|
 }|j|jd}n|dkra| }|j|jd}| ||\}}}||7 }Y qw td| d S )Nr   r,   )pkr-   z(Successfully deleted {} model instances.r   )r   r+   r/   objectsall__getattribute__updategetMultipleObjectsReturnedfilterr,   excluder8   r-   merge_model_instancesr
   format)selfargsoptionsr   field_namesr.   total_deleted_objects_countinstancekwargsr5   instance_field_value	instancesprimary_objectalias_objectsdeleted_objectsdeleted_objects_countr   r   r   handlej   s8   

zCommand.handlec                 C   s`  t  }ttdd |j }ttdd |}ttdd |}g }d}|D ]}|D ]V}	|	j}
t||
}| D ]G}zt||
| t||
	| W q: t
y   t||
j}|	 ||	 |i}|jjd	i |}|D ]}t||	 | |  qpY q:w q,|D ]X}|jr| }
t||
}| D ]}|jj}t||| |  qq|js|jr|j}
t||
}t||
}|du rt||
| |  q|jr| jd||j |  q|D ]-}i }| ||j< ||||j< |jjjd	i |}|D ]}t||j| |  qq|jr*||g7 }| jd||j |  |d7 }q'|||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   
   | j du S NT)is_relationxr   r   r   <lambda>      
 z/Command.merge_model_instances.<locals>.<lambda>c                 S   rQ   rR   many_to_manyrT   r   r   r   rV      rW   c                 S   rQ   )NFrX   rT   r   r   r   rV      rW   r   NzDeleted {} with id {}
r   r   ) r6   r#   r?   r   r    r   getattrr:   removeaddAttributeErrorthroughm2m_reverse_field_namem2m_field_namer9   setattrsaveone_to_manyget_accessor_namer   
one_to_onemany_to_onestdoutwriterB   iddelete_get_pk_valfk_fieldget_content_typect_fieldr   )rC   rL   rM   r4   related_fieldsmany_to_many_fieldsrN   rO   alias_objectmany_to_many_fieldalias_varnamerelated_objectsobjthrough_modelrI   through_model_instancesrH   related_fieldr5   related_objectprimary_related_objectr   filter_kwargsgeneric_related_objectr   r   r   rA      s   










zCommand.merge_model_instancesN)	r   
__module____qualname__helpr   rP   r   atomicrA   r   r   r   r   r7   \   s    
 r7   N)django.appsr   "django.contrib.contenttypes.fieldsr   django.core.managementr   	django.dbr   "django_extensions.management.utilsr   r   r+   r/   r6   r7   r   r   r   r   <module>   s   1

