3
(h(                 @   s   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 d dlmZ G d	d
 d
eZG dd deeZG dd deeZdS )    )absolute_importunicode_literals)models)ValidationError)BaseGenericInlineFormSet)ContentType)BaseInlineFormSet)
force_text)xrangec                   sL   e Zd ZdddZdd ZdddZ fd	d
ZdddZdddZ  Z	S )NestedInlineFormSetMixinTc       
         s   g  _ g  _g  _|s.g  _ fdd}| _ j }g }x4t jD ]&\}}||_t	||k |_
|j| qFW  j|}g }g }xH|D ]@} j|||}	|	dk	r||	g7 }n|j}	 j|s|j|	 qW |jdd d |S )z
        Saves model instances for every form, adding and changing instances
        as necessary, and returns the list of instances.
        c                 s   x j D ]} | j  qW d S )N)saved_formssave_m2m)form)self F/tmp/pip-install-q3hcpn_q/django-nested-admin/nested_admin/formsets.pyr      s    z/NestedInlineFormSetMixin.save.<locals>.save_m2mNc             S   s   | j S )N)_list_position)ir   r   r   <lambda>C   s    z/NestedInlineFormSetMixin.save.<locals>.<lambda>)key)changed_objectsdeleted_objectsnew_objectsr   r   initial_form_count	enumerateformsr   bool_is_initialappendprocess_forms_pre_saveget_saved_instance_for_forminstance_should_delete_formsort)
r   commitr   r   r   r   r   form_instancessaved_instancesr!   r   )r   r   save   s2    


zNestedInlineFormSetMixin.savec                s4   t | dd  dk	r0|j fdddj d |S )z
        Sort by the sortable_field_name of the formset, if it has been set.

        Allows customizable sorting and modification of self.forms before
        they're iterated through in save().

        Returns list of forms.
        Zsortable_field_nameNc                s   t | d diS )Ncleaned_datar   )getattr)f)
sort_fieldr   r   r   Q   s    zANestedInlineFormSetMixin.process_forms_pre_save.<locals>.<lambda>)r   r   )r)   r#   get)r   r   r   )r+   r   r   F   s    	z/NestedInlineFormSetMixin.process_forms_pre_saveNc       	      C   s   d }|j r |j jjr |j jjj}d }|j rBt|drB|jj|}t|t	j
rT|j}|d k	ryt|j || W n0 tk
r   |j jjj }t|j || Y nX |jr| j|g|}n| j|g|}t|r|d }|j|_|S d S d S )Nr(   r   )r!   _metapknameerrorshasattrr(   r,   
isinstancer   ZModelsetattr
ValueErrorget_attnamer   save_existing_objectssave_new_objectslenr   )	r   r   r$   r%   pk_nameZpk_valZ
pk_attnameZ	instancesr!   r   r   r   r    T   s,    z4NestedInlineFormSetMixin.get_saved_instance_for_formc                s    j stt j S t ds fddtd j D } fdd|D } jjj }|j	|d}|j
s||j jjjj}| _ jS )z5
        TODO: document this extended method
        Z
__querysetc                s&   g | ]}d  j | jjjjf qS )z%s-%s)
add_prefixmodelr-   r.   r/   ).0r   )r   r   r   
<listcomp>y   s   z9NestedInlineFormSetMixin.get_queryset.<locals>.<listcomp>r   c                s$   g | ]} j j|r j j|qS r   )datar,   )r<   Zpk_key)r   r   r   r=   {   s    )Zpk__in)r>   superr   get_querysetr1   r
   r   r;   Z_default_managerfilterorderedZorder_byr-   r.   r/   Z#_NestedInlineFormSetMixin__queryset)r   Zpk_keysZpk_valsqs)	__class__)r   r   r@   q   s    

z%NestedInlineFormSetMixin.get_querysetc             C   sp  |sg S g }| j }xV|D ]L}| jj}t|dsT|j| jj|j|j|j	|}n
|j
|}| j|rn|}n\y|j| j|}W n: tk
r   d|j|j	|< |j| j|g| wY nX t|d|}d}	|	dko|jo|r8|jj}
y|
jj|d}	W n: |
jk
r6   |r2t|jjt|kr2|j}	Y nX |	dkrL| j|}	||kr| jj|	 t| dr~| j|	|d q|r|	j  qtjj| jjj }}| jj }}|jjr| jjj|jjd}t| dt| d	d}|rt||j  }t| d
d}|rt||j  }|j! s0||ks0||kr| j"j|	|j#f |j| j$||	|d |s| j%j| qW |S )z
        Identical to parent class, except ``self.initial_forms`` is replaced
        with ``initial_forms``, passed as parameter.
        
_raw_value r.   N)r.   delete_existing)r$   Zfkct_fk_fieldct_field)&Zdeleted_formsZ	_pk_fieldr/   r1   fieldsZwidgetZvalue_from_datadictr>   filesr:   rE   r"   cleanr   extendr7   r)   r!   rD   objectsr,   ZDoesNotExistr	   r.   Z_existing_objectr   r   rG   deleter   get_for_modelr;   r5   has_changedr   Zchanged_datasave_existingr   )r   Zinitial_formsr$   r&   Zforms_to_deleter   r9   Zraw_pk_valueZpk_valueobjZ	model_clsZ
old_ct_valZct_valZ
old_fk_valZfk_valZoriginal_instanceZfk_fieldrI   r   r   r   r6      sh    






z.NestedInlineFormSetMixin.save_existing_objectsc             C   sn   g }|dkr|S xL|D ]D}|j  s$q| jr6| j|r6q|j| j||d |s| jj| qW | jj| |S )z
        Identical to parent class, except ``self.extra_forms`` is replaced
        with ``extra_forms``, passed as parameter, and self.new_objects is
        replaced with ``new_objects``.
        N)r$   )rQ   Z
can_deleter"   r   save_newr   r   rM   )r   Zextra_formsr$   r   r   r   r   r   r7      s    
z)NestedInlineFormSetMixin.save_new_objects)T)N)NT)NT)
__name__
__module____qualname__r'   r   r    r@   r6   r7   __classcell__r   r   )rD   r   r      s   
8

Nr   c               @   s   e Zd ZdZdS )NestedInlineFormSetzK
    The nested InlineFormSet for the common case (ForeignKey inlines)
    N)rU   rV   rW   __doc__r   r   r   r   rY      s   rY   c               @   s   e Zd ZdZdddZdS )NestedBaseGenericInlineFormSetzP
    The nested InlineFormSet for inlines of generic content-type relations
    Tc             C   sD   t |j| jj tjj| jj t |j| jj | jj |j	|dS )z@Saves and returns an existing model instance for the given form.)r$   )
r3   r!   rI   r5   r   rN   rP   r.   rH   r'   )r   r   r!   r$   r   r   r   rR      s
    
z,NestedBaseGenericInlineFormSet.save_existingN)T)rU   rV   rW   rZ   rR   r   r   r   r   r[      s   r[   N)
__future__r   r   Z	django.dbr   Zdjango.core.exceptionsr   Z!django.contrib.contenttypes.formsr   Z"django.contrib.contenttypes.modelsr   Zdjango.forms.modelsr   Zdjango.utils.encodingr	   Zdjango.utils.six.movesr
   objectr   rY   r[   r   r   r   r   <module>   s    f