3
gP%                 @   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   sP   t j } d}x&| D ]}td||jf  |d7 }qW ttd}| |d  }|S )N   z%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   y/var/www/tester-filtro-web/env/lib/python3.6/site-packages/django_extensions/management/commands/merge_model_instances.pyget_model_to_deduplicate
   s    
r   c       	         sd  dd | j j D }d}x$|D ]}td||f  |d7 }qW d}x0|srttd}|td|krhd}qDtd qDW ||d  g d}x|s^ fd	d|D }d}x$|D ]}td||f  |d7 }qW td
 d}x|sZtd tdj d  td}|dkrd}d}qt|ttdt|d krP |t|d  g7  d}qtd qW qW  S )Nc             S   s   g | ]
}|j qS r   )name).0fieldr   r   r   
<listcomp>   s    z#get_field_names.<locals>.<listcomp>r   z%s. %sFzEEnter the number of the (first) field you would like to de-duplicate.Tz Invalid input. Please try again.c                s   g | ]}| k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   Z	validatedZfirst_fielddoneZavailable_fieldsZadditional_fieldr   )r   r   get_field_names   sD    


 r#   c              C   s   xt d} | dkr| S qW d S )Nz
            Do you want to keep the first or last duplicate instance?
            Enter "first" or "last" to continue.
            firstlast)r$   r%   )r   )first_or_lastr   r   r   keep_first_or_last_instanceD   s
    r'   c              C   sF   g } x<t j D ]0}x*|jj D ]\}}t|tr| j| qW qW | 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    
r.   c               @   s,   e Zd ZdZedd Zej 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}x|jj D ]}i }x$|D ]}	|j|	}
|j|	|
i q2W y|jjf | W q$ |jk
r   |jj	f |}|dkr|j
 }|j|jd}n|dkr|j }|j|jd}| j||\}}}||7 }Y q$X q$W tdj| d S )Nr   r$   )pkr%   z(Successfully deleted {} model instances.)r   r#   r'   objectsall__getattribute__updategetZMultipleObjectsReturnedfilterr$   excluder0   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   s.    

zCommand.handlec             C   s  t  }ttdd |jj }ttdd |}ttdd |}g }d}x8|D ].}x|D ]}	|	j}
t||
}x|j D ]}y$t||
j| t||
j	| W q| t
k
r   t||
j}|	j ||	j |i}|jjf |}x$|D ]}t||	j | |j  qW Y q|X q|W q^W x|D ]}|jrn|j }
t||
}x|j D ]"}|jj}t||| |j  qFW np|js~|jr|j}
t||
}t||
}|dkrt||
| |j  n&|jr| jjdj||j |j  qW xf|D ]^}i }|j ||j< |j|||j< |jjjf |}x$|D ]}t||j| |j  q&W qW |jrR||g7 }| jjdj||j |j  |d7 }qRW |||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kS )NT)Zis_relation)xr   r   r   <lambda>   s    z/Command.merge_model_instances.<locals>.<lambda>c             S   s
   | j dkS )NT)many_to_many)rE   r   r   r   rF      s    c             S   s
   | j dkS )NF)rG   )rE   r   r   r   rF      s    r   NzDeleted {} with id {}
r   ) r.   r   r6   r   r   r   getattrr2   removeaddAttributeErrorZthroughZm2m_reverse_field_nameZm2m_field_namer1   setattrsaveZone_to_manyZget_accessor_namer   Z
one_to_oneZmany_to_onestdoutwriter9   iddeleteZ_get_pk_valZfk_fieldget_content_typeZct_fieldr   )r:   r@   rA   r,   Zrelated_fieldsZmany_to_many_fieldsrB   rC   Zalias_objectZmany_to_many_fieldZalias_varnameZrelated_objectsobjZthrough_modelr?   Zthrough_model_instancesr>   Zrelated_fieldr-   Zrelated_objectZprimary_related_objectr   Zfilter_kwargsZgeneric_related_objectr   r   r   r8      s~    













zCommand.merge_model_instancesN)	r
   
__module____qualname__helpr   rD   r   Zatomicr8   r   r   r   r   r/   X   s   r/   N)Zdjango.appsr   Z"django.contrib.contenttypes.fieldsr   Zdjango.core.managementr   Z	django.dbr   Z"django_extensions.management.utilsr   r   r#   r'   r.   r/   r   r   r   r   <module>   s   /

