U
    mfLR                     @   s   d dl 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mZmZ d dlmZ d dlmZ d d	lmZ d
ZdZdZdZdZdZdZd ZdZG dd deZG dd deZ e ddddddddddfddZ!dd Z"dS )    )ValidationError)Form)BooleanFieldIntegerField)get_default_renderer)	ErrorListRenderableFormMixin)CheckboxInputHiddenInputNumberInput)cached_property)gettext_lazy)ngettext_lazy)BaseFormSetformset_factory	all_validTOTAL_FORMSINITIAL_FORMSMIN_NUM_FORMSMAX_NUM_FORMSZORDERDELETEi  c                       sP   e Zd ZdZdZeedZeedZededZ	ededZ
 fddZ  ZS )ManagementFormz
    Keep track of how many form instances are displayed on the page. If adding
    new forms via JavaScript, you should increment the count field of this form
    as well.
    zdjango/forms/div.html)widgetF)requiredr   c                    s&   t   }|td |td |S Nr   )superclean
setdefaultTOTAL_FORM_COUNTINITIAL_FORM_COUNT)selfcleaned_data	__class__ 9/tmp/pip-unpacked-wheel-siwebuq3/django/forms/formsets.pyr   -   s    
zManagementForm.clean)__name__
__module____qualname____doc__template_namer   r
   r   r   r   r   r   __classcell__r$   r$   r"   r%   r      s   

r   c                   @   s  e Zd ZdZeZeZede	ddde	ddddZ
d	Zd
ZdZdZdddddeddfddZdd Zdd Zdd Zdd Zdd Zedd Zdd Zdd  Zed!d" Zd#d$ Zd%d& Zed'd( Zed)d* Zed+d, Z ed-d. Z!ed/d0 Z"ed1d2 Z#e$d3d4 Z%e$d5d6 Z&e$d7d8 Z'd9d: Z(ed;d< Z)d=d> Z*d?d@ Z+dAdB Z,dCdD Z-dEdF Z.dGdH Z/dIdJ Z0dKdL Z1dMdN Z2edOdP Z3edQdR Z4dSdT Z5dS )Ur   z;
    A collection of instances of the same Form class.
    zManagementForm data is missing or has been tampered with. Missing fields: %(field_names)s. You may need to file a bug report if the issue persists.z#Please submit at most %(num)d form.z$Please submit at most %(num)d forms.numz$Please submit at least %(num)d form.z%Please submit at least %(num)d forms.)missing_management_formtoo_many_formstoo_few_formszdjango/forms/formsets/div.htmlzdjango/forms/formsets/p.htmlz django/forms/formsets/table.htmlzdjango/forms/formsets/ul.htmlNzid_%sc	                 C   s   |d k	p|d k	| _ |p|  | _|| _|p,i | _|p6i | _|| _|pFi | _|| _d | _	d | _
i }	tt| jD ]}
|	t|
di  qn|d k	r|	| |	| _d S )Ndefault_error_messages)is_boundget_default_prefixprefixauto_iddatafilesinitialform_kwargserror_class_errors_non_form_errorsreversedtype__mro__updategetattrerror_messages)r    r5   r6   r4   r3   r7   r9   r8   rA   messagesclsr$   r$   r%   __init__S   s     



zBaseFormSet.__init__c                 C   s
   t | jS )z5Yield the forms in the order they should be rendered.)iterformsr    r$   r$   r%   __iter__p   s    zBaseFormSet.__iter__c                 C   s
   | j | S )zAReturn the form at the given index, based on the rendering order.rF   r    indexr$   r$   r%   __getitem__t   s    zBaseFormSet.__getitem__c                 C   s
   t | jS N)lenrF   rG   r$   r$   r%   __len__x   s    zBaseFormSet.__len__c                 C   s   dS )zt
        Return True since all formsets have a management form which is not
        included in the length.
        Tr$   rG   r$   r$   r%   __bool__{   s    zBaseFormSet.__bool__c                 C   sN   | j d krd}n$| jo2| j o2tdd | j D  }d| jj| j||  f S )NUnknownc                 s   s   | ]
}|V  qd S rM   r$   .0form_errorsr$   r$   r%   	<genexpr>   s     z'BaseFormSet.__repr__.<locals>.<genexpr>z&<%s: bound=%s valid=%s total_forms=%s>)r:   r1   r;   anyr#   r(   total_form_count)r    is_validr$   r$   r%   __repr__   s    
zBaseFormSet.__repr__c                 C   s^   | j r(t| j| j| j| jd}|  n2t| j| jt|  t	| 
 t| jt| ji| jd}|S )z4Return the ManagementForm instance for this FormSet.)r4   r3   renderer)r4   r3   r7   rZ   )r1   r   r5   r4   r3   rZ   
full_cleanr   rW   r   initial_form_countMIN_NUM_FORM_COUNTmin_numMAX_NUM_FORM_COUNTmax_numr    formr$   r$   r%   management_form   s.    
    zBaseFormSet.management_formc                 C   sx   | j rt| jjt | jS |  }t|| j| j	 }|| j
  krJdkrTn n|}n || j
  krjdkrtn n| j
}|S )z1Return the total number of forms in this FormSet.r   )r1   minrc   r!   r   absolute_maxr\   maxr^   extrar`   )r    initial_formsZtotal_formsr$   r$   r%   rW      s    
 zBaseFormSet.total_form_countc                 C   s*   | j r| jjt S | jr"t| jnd}|S )z=Return the number of forms that are required in this FormSet.r   )r1   rc   r!   r   r7   rN   )r    rh   r$   r$   r%   r\      s    zBaseFormSet.initial_form_countc                    s    fddt   D S )z+Instantiate forms at first property access.c                    s    g | ]} j |f |qS r$   )_construct_formget_form_kwargsrS   irG   r$   r%   
<listcomp>   s   z%BaseFormSet.forms.<locals>.<listcomp>)rangerW   rG   r$   rG   r%   rF      s    

zBaseFormSet.formsc                 C   s
   | j  S )z
        Return additional keyword arguments for each individual formset form.

        index will be None if the form being constructed is a new empty
        form.
        )r8   copyrJ   r$   r$   r%   rj      s    zBaseFormSet.get_form_kwargsc                 K   s   | j | || jd| jd}| jr6| j|d< | j|d< | jrld|krlz| j| |d< W n tk
rj   Y nX || 	 kr|| j
krd|d< || | jf |}| || |S )z;Instantiate and return the i-th form instance in a formset.F)r4   r3   r9   use_required_attributerZ   r5   r6   r7   Tempty_permitted)r4   
add_prefixr9   rZ   r1   r5   r6   r7   
IndexErrorr\   r^   r?   rb   
add_fields)r    rl   kwargsdefaultsrb   r$   r$   r%   ri      s(    



zBaseFormSet._construct_formc                 C   s   | j d|   S )z7Return a list of all the initial forms in this formset.NrF   r\   rG   r$   r$   r%   rh      s    zBaseFormSet.initial_formsc                 C   s   | j |  d S )z5Return a list of all the extra forms in this formset.Nrw   rG   r$   r$   r%   extra_forms   s    zBaseFormSet.extra_formsc                 C   s@   | j f | j| dddd| d d| ji}| |d  |S )NZ
__prefix__TF)r4   r3   rq   rp   rZ   )rb   r4   rr   rj   rZ   rt   ra   r$   r$   r%   
empty_form  s    zBaseFormSet.empty_formc                 C   s(   |   std| jj dd | jD S )zX
        Return a list of form.cleaned_data dicts for every form in self.forms.
        z+'%s' object has no attribute 'cleaned_data'c                 S   s   g | ]
}|j qS r$   )r!   rS   rb   r$   r$   r%   rm     s     z,BaseFormSet.cleaned_data.<locals>.<listcomp>)rX   AttributeErrorr#   r&   rF   rG   r$   r$   r%   r!     s
    
zBaseFormSet.cleaned_datac                    sv      r jsg S t dsbg  _t jD ]4\}}|  krJ| sJq, |r, j	| q, fdd jD S )z:Return a list of forms that have been marked for deletion._deleted_form_indexesc                    s   g | ]} j | qS r$   rI   rk   rG   r$   r%   rm   )  s     z-BaseFormSet.deleted_forms.<locals>.<listcomp>)
rX   
can_deletehasattrr|   	enumeraterF   r\   has_changed_should_delete_formappend)r    rl   rb   r$   rG   r%   deleted_forms  s    

zBaseFormSet.deleted_formsc                    s      r jstd jj t dsg  _t jD ]F\}}| 	 krV|
 sVq8 jrh |rhq8 j||jt f q8dd } jj|d  fdd jD S )z
        Return a list of form in the order specified by the incoming data.
        Raise an AttributeError if ordering is not allowed.
        z,'%s' object has no attribute 'ordered_forms'	_orderingc                 S   s   | d d krdS d| d fS )N   )r   r   r   r$   )kr$   r$   r%   compare_ordering_keyI  s    z7BaseFormSet.ordered_forms.<locals>.compare_ordering_key)keyc                    s   g | ]} j |d   qS )r   rI   rk   rG   r$   r%   rm   Q  s     z-BaseFormSet.ordered_forms.<locals>.<listcomp>)rX   	can_orderr{   r#   r&   r~   r   r   rF   r\   r   r}   r   r   r!   ORDERING_FIELD_NAMEsort)r    rl   rb   r   r$   rG   r%   ordered_forms+  s    

zBaseFormSet.ordered_formsc                 C   s   dS )Nrb   r$   rC   r$   r$   r%   r2   S  s    zBaseFormSet.get_default_prefixc                 C   s   | j S rM   )deletion_widgetr   r$   r$   r%   get_deletion_widgetW  s    zBaseFormSet.get_deletion_widgetc                 C   s   | j S rM   )ordering_widgetr   r$   r$   r%   get_ordering_widget[  s    zBaseFormSet.get_ordering_widgetc                 C   s   | j dkr|   | j S )z
        Return an ErrorList of errors that aren't associated with a particular
        form -- i.e., from formset.clean(). Return an empty ErrorList if there
        are none.
        N)r;   r[   rG   r$   r$   r%   non_form_errors_  s    
zBaseFormSet.non_form_errorsc                 C   s   | j dkr|   | j S )z:Return a list of form.errors for every form in self.forms.N)r:   r[   rG   r$   r$   r%   errorsi  s    
zBaseFormSet.errorsc                 C   s    t |  tdd | jD  S )z<Return the number of errors across all forms in the formset.c                 s   s   | ]}t |V  qd S rM   )rN   rR   r$   r$   r%   rU   r  s    z0BaseFormSet.total_error_count.<locals>.<genexpr>)rN   r   sumr   rG   r$   r$   r%   total_error_countp  s    zBaseFormSet.total_error_countc                 C   s   |j tdS )z7Return whether or not the form was marked for deletion.F)r!   getDELETION_FIELD_NAMEra   r$   r$   r%   r   v  s    zBaseFormSet._should_delete_formc                    s6    j s
dS  j t fdd jD }|o4   S )z1Return True if every form in self.forms is valid.Fc                    s$   g | ]} j r |s| qS r$   )r}   r   rX   rz   rG   r$   r%   rm     s    
z(BaseFormSet.is_valid.<locals>.<listcomp>)r1   r   allrF   r   )r    Zforms_validr$   rG   r%   rX   z  s    
zBaseFormSet.is_validc              
      s  g  _  jd jd _d} js&dS  j slt jd dd	 fdd	 jj
D idd
} j| t jD ]H\}}| s|  kr|d7 }|j
} jr |rqv j | qvz jr  t j  jks jjt  jkrt jd d ji dd jrR  t j |  jk rRt jd d ji dd   W n: tk
r } z j|jd jd _W 5 d}~X Y nX dS )ze
        Clean all of self.data and populate self._errors and
        self._non_form_errors.
        Znonform)r9   rZ   r   Nr-   field_namesz, c                 3   s   | ]} j |V  qd S rM   )rc   rr   )rS   
field_namerG   r$   r%   rU     s   z)BaseFormSet.full_clean.<locals>.<genexpr>)paramscoder   r.   r,   )r   r/   )r:   r9   rZ   r;   r1   rc   rX   r   rA   joinr   r   r   rF   r   r\   r}   r   validate_maxrW   rN   r   r`   r!   r   re   validate_minr^   r   Z
error_list)r    Zempty_forms_counterrorrl   rb   rT   er$   rG   r%   r[     s|     
 
zBaseFormSet.full_cleanc                 C   s   dS )a  
        Hook for doing any extra formset-wide cleaning after Form.clean() has
        been called on every form. Any ValidationError raised by this method
        will not be associated with a particular form; it will be accessible
        via formset.non_form_errors()
        Nr$   rG   r$   r$   r%   r     s    zBaseFormSet.cleanc                 C   s   t dd | D S )z5Return True if data in any form differs from initial.c                 s   s   | ]}|  V  qd S rM   )r   rz   r$   r$   r%   rU     s     z*BaseFormSet.has_changed.<locals>.<genexpr>)rV   rG   r$   r$   r%   r     s    zBaseFormSet.has_changedc                 C   s   |   }| jr^|dk	rB||k rBttd|d d|  d|jt< nttdd|  d|jt< | jr| jsr||k rt	tdd| 
 d|jt< dS )z8A hook for adding extra fields on to each form instance.NZOrderr   F)labelr7   r   r   )r   r   r   ZDelete)r\   r   r   _r   fieldsr   r}   can_delete_extrar   r   r   )r    rb   rK   r\   r$   r$   r%   rt     s(    zBaseFormSet.add_fieldsc                 C   s   d| j |f S )Nz%s-%s)r3   rJ   r$   r$   r%   rr     s    zBaseFormSet.add_prefixc                 C   s"   | j r| j d  S | j S dS )zv
        Return True if the formset needs to be multipart, i.e. it
        has FileInput, or False otherwise.
        r   N)rF   is_multipartry   rG   r$   r$   r%   r     s    zBaseFormSet.is_multipartc                 C   s   | j r| j d jS | jjS d S r   )rF   mediary   rG   r$   r$   r%   r     s    zBaseFormSet.mediac                 C   s   | j jS rM   )rZ   Zformset_template_namerG   r$   r$   r%   r*     s    zBaseFormSet.template_namec                 C   s   d| iS )Nformsetr$   rG   r$   r$   r%   get_context  s    zBaseFormSet.get_context)6r&   r'   r(   r)   r	   r   r   r   r   r   r0   Ztemplate_name_divZtemplate_name_pZtemplate_name_tableZtemplate_name_ulr   rD   rH   rL   rO   rP   rY   r   rc   rW   r\   rF   rj   ri   propertyrh   rx   ry   r!   r   r   classmethodr2   r   r   r   r   r   r   rX   r[   r   r   rt   rr   r   r   r*   r   r$   r$   r$   r%   r   6   s   

	
	






'




D	


r   r   FNTc                 C   sn   |dkrt }|dkrt}|	dkr(|t }	||	kr8td| ||||
|||	|||pTt d}t| jd |f|S )z*Return a FormSet for the given form class.Nz5'absolute_max' must be greater or equal to 'max_num'.)rb   rg   r   r}   r   r^   r`   re   r   r   rZ   ZFormSet)DEFAULT_MIN_NUMDEFAULT_MAX_NUM
ValueErrorr   r=   r&   )rb   r   rg   r   r}   r`   r   r^   r   re   r   rZ   attrsr$   r$   r%   r     s*    r   c                 C   s   t dd | D S )z8Validate every formset and return True if all are valid.c                 S   s   g | ]}|  qS r$   )rX   )rS   r   r$   r$   r%   rm   @  s     zall_valid.<locals>.<listcomp>)r   )Zformsetsr$   r$   r%   r   =  s    r   )#Zdjango.core.exceptionsr   Zdjango.formsr   Zdjango.forms.fieldsr   r   Zdjango.forms.renderersr   Zdjango.forms.utilsr   r   Zdjango.forms.widgetsr	   r
   r   Zdjango.utils.functionalr   Zdjango.utils.translationr   r   r   __all__r   r   r]   r_   r   r   r   r   r   r   r   r   r$   r$   r$   r%   <module>   sF      b
*