U
    HaM                  
   @   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 d dlmZ d dlmZ d d	lmZ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eG dd dZ e dddddddddf
ddZ!dd Z"dS )    )ValidationError)Form)BooleanFieldIntegerField)	ErrorList)HiddenInputNumberInput)cached_property)	html_safe)	mark_safe)gettext_lazyngettext)BaseFormSetformset_factory	all_validZTOTAL_FORMSZINITIAL_FORMSZMIN_NUM_FORMSZMAX_NUM_FORMSZORDERDELETEi  c                       s,   e Zd ZdZ fd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.
    c                    sV   t td| jt< t td| jt< t dtd| jt< t dtd| jt< t j|| d S )N)widgetF)requiredr   )	r   r   Zbase_fieldsTOTAL_FORM_COUNTINITIAL_FORM_COUNTMIN_NUM_FORM_COUNTMAX_NUM_FORM_COUNTsuper__init__)selfargskwargs	__class__ 9/tmp/pip-unpacked-wheel-3jxiddxt/django/forms/formsets.pyr   "   s
    zManagementForm.__init__c                    s&   t   }|td |td |S Nr   )r   clean
setdefaultr   r   )r   cleaned_datar   r    r!   r#   ,   s    
zManagementForm.clean)__name__
__module____qualname____doc__r   r#   __classcell__r    r    r   r!   r      s   
r   c                   @   sz  e Zd ZdZeZdedi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&d' Zed(d) Zed*d+ Zed,d- Zd.d/ Z ed0d1 Z!d2d3 Z"d4d5 Z#d6d7 Z$d8d9 Z%d:d; Z&d<d= Z'd>d? Z(d@dA Z)dBdC Z*edDdE Z+dFdG Z,dHdI Z-dJdK Z.dS )Lr   z;
    A collection of instances of the same Form class.
    missing_management_formzManagementForm 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.Nz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   r1   r2   r0   r/   r3   r5   r4   r=   messagesclsr    r    r!   r   B   s     



zBaseFormSet.__init__c                 C   s   |   S Nas_tabler   r    r    r!   __str__W   s    zBaseFormSet.__str__c                 C   s
   t | jS )z5Yield the forms in the order they should be rendered.)iterformsrC   r    r    r!   __iter__Z   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__^   s    zBaseFormSet.__getitem__c                 C   s
   t | jS r@   )lenrF   rC   r    r    r!   __len__b   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    rC   r    r    r!   __bool__e   s    zBaseFormSet.__bool__c                 C   sV   | j r$t| j| j| jd}|  n.t| j| jt|  t| 	 t
| jt| jid}|S )z4Return the ManagementForm instance for this FormSet.)r0   r/   )r0   r/   r3   )r-   r   r1   r0   r/   
full_cleanr   total_form_countr   initial_form_countr   min_numr   max_numr   formr    r    r!   management_forml   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   )r-   minrV   r%   r   absolute_maxrQ   maxrR   extrarS   )r   initial_formsZtotal_formsr    r    r!   rP   {   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   )r-   rV   r%   r   r3   rL   )r   r[   r    r    r!   rQ      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.0irC   r    r!   
<listcomp>   s   z%BaseFormSet.forms.<locals>.<listcomp>)rangerP   rC   r    rC   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.
        )r4   copyrI   r    r    r!   r]      s    zBaseFormSet.get_form_kwargsc                 K   s   | j | || jdd}| jr2| j|d< | j|d< | jrhd|krhz| j| |d< W n tk
rf   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)r0   r/   r5   use_required_attributer1   r2   r3   Tempty_permitted)r0   
add_prefixr5   r-   r1   r2   r3   
IndexErrorrQ   rR   r;   rU   
add_fields)r   r`   r   defaultsrU   r    r    r!   r\      s&    	


zBaseFormSet._construct_formc                 C   s   | j d|   S )z7Return a list of all the initial forms in this formset.NrF   rQ   rC   r    r    r!   r[      s    zBaseFormSet.initial_formsc                 C   s   | j |  d S )z5Return a list of all the extra forms in this formset.Nrj   rC   r    r    r!   extra_forms   s    zBaseFormSet.extra_formsc                 C   s8   | j f | j| dddd| d }| |d  |S )NZ
__prefix__TF)r0   r/   re   rd   )rU   r0   rf   r]   rh   rT   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%   r_   rU   r    r    r!   ra      s     z,BaseFormSet.cleaned_data.<locals>.<listcomp>)is_validAttributeErrorr   r&   rF   rC   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    rH   r^   rC   r    r!   ra      s     z-BaseFormSet.deleted_forms.<locals>.<listcomp>)
rn   
can_deletehasattrrp   	enumeraterF   rQ   has_changed_should_delete_formappend)r   r`   rU   r    rC   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   )ry   r   r   r    )kr    r    r!   compare_ordering_key  s    z7BaseFormSet.ordered_forms.<locals>.compare_ordering_key)keyc                    s   g | ]} j |d   qS )r   rH   r^   rC   r    r!   ra     s     z-BaseFormSet.ordered_forms.<locals>.<listcomp>)rn   	can_orderro   r   r&   rr   rx   rs   rF   rQ   rt   rq   ru   rv   r%   ORDERING_FIELD_NAMEsort)r   r`   rU   r{   r    rC   r!   ordered_forms   s    
zBaseFormSet.ordered_formsc                 C   s   dS )NrU   r    r?   r    r    r!   r.     s    zBaseFormSet.get_default_prefixc                 C   s   | j S r@   )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)r7   rO   rC   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)r6   rO   rC   r    r    r!   errors,  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 r@   )rL   )r_   form_errorsr    r    r!   	<genexpr>6  s     z0BaseFormSet.total_error_count.<locals>.<genexpr>)rL   r   sumr   rC   r    r    r!   total_error_count3  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_NAMErT   r    r    r!   ru   8  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    )rq   ru   rn   rm   rC   r    r!   ra   D  s    
z(BaseFormSet.is_valid.<locals>.<listcomp>)r-   r   allrF   r   )r   Zforms_validr    rC   r!   rn   <  s    zBaseFormSet.is_validc              
      s  g  _    _d} jsdS  j sdt 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 |rqn j 
| qnz jr؈  t j  jks jjt  jkrttd
d j j dd jrJ  t j |  jk rJttdd j j dd   W n2 tk
r } z |j _W 5 d}~X Y nX dS )ze
        Clean all of self.data and populate self._errors and
        self._non_form_errors.
        r   Nr+   field_namesz, c                 3   s   | ]} j |V  qd S r@   )rV   rf   )r_   
field_namerC   r    r!   r   Z  s   z)BaseFormSet.full_clean.<locals>.<genexpr>)paramscodery   zPlease submit at most %d form.zPlease submit at most %d forms.Ztoo_many_forms)r   zPlease submit at least %d form.z Please submit at least %d forms.Ztoo_few_forms)r6   r5   r7   r-   rV   rn   r   r=   joinr   rv   rs   rF   rt   rQ   rq   ru   validate_maxrP   rL   rw   rS   r%   r   rX   r   validate_minrR   r#   Z
error_list)r   Zempty_forms_counterrorr`   rU   r   er    rC   r!   rO   J  sj    

 
  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    rC   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 r@   )rt   rm   r    r    r!   r     s     z*BaseFormSet.has_changed.<locals>.<genexpr>)anyrC   r    r    r!   rt     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Orderry   F)labelr3   r   r   )r   r   r   ZDelete)r   r   )rQ   r}   r   _r   fieldsr~   rq   can_delete_extrar   r   )r   rU   rJ   rQ   r    r    r!   rh     s     zBaseFormSet.add_fieldsc                 C   s   d| j |f S )Nz%s-%s)r/   rI   r    r    r!   rf     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_multipartrl   rC   r    r    r!   r     s    zBaseFormSet.is_multipartc                 C   s   | j r| j d jS | jjS d S r"   )rF   mediarl   rC   r    r    r!   r     s    zBaseFormSet.mediac                 C   s*   d dd | D }tt| jd | S )zLReturn this formset rendered as HTML <tr>s -- excluding the <table></table>. c                 s   s   | ]}|  V  qd S r@   rA   rm   r    r    r!   r     s     z'BaseFormSet.as_table.<locals>.<genexpr>
r   r   strrV   r   rF   r    r    r!   rB     s    zBaseFormSet.as_tablec                 C   s*   d dd | D }tt| jd | S )z*Return this formset rendered as HTML <p>s.r   c                 s   s   | ]}|  V  qd S r@   )as_prm   r    r    r!   r     s     z#BaseFormSet.as_p.<locals>.<genexpr>r   r   r   r    r    r!   r     s    zBaseFormSet.as_pc                 C   s*   d dd | D }tt| jd | S )z+Return this formset rendered as HTML <li>s.r   c                 s   s   | ]}|  V  qd S r@   )as_ulrm   r    r    r!   r     s     z$BaseFormSet.as_ul.<locals>.<genexpr>r   r   r   r    r    r!   r     s    zBaseFormSet.as_ul)/r&   r'   r(   r)   r   r   r   r,   r   r   rD   rG   rK   rM   rN   r	   rV   rP   rQ   rF   r]   r\   propertyr[   rk   rl   r%   rw   r   classmethodr.   r   r   r   r   ru   rn   rO   r#   rt   rh   rf   r   r   rB   r   r   r    r    r    r!   r   5   sv      

	
	





$



7	

r   ry   FNTc                 C   sf   |dkrt }|dkrt}|	dkr(|t }	||	kr8td| ||||
|||	||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'.)
rU   rZ   r}   rq   r   rR   rS   rX   r   r   ZFormSet)DEFAULT_MIN_NUMDEFAULT_MAX_NUM
ValueErrorr9   r&   )rU   formsetrZ   r}   rq   rS   r   rR   r   rX   r   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    )rn   )r_   r   r    r    r!   ra     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.utilsr   Zdjango.forms.widgetsr   r   Zdjango.utils.functionalr	   Zdjango.utils.htmlr
   Zdjango.utils.safestringr   Zdjango.utils.translationr   r   r   __all__r   r   r   r   r~   r   r   r   r   r   r   r   r    r    r    r!   <module>   sB          
!