3
v^H                 @   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fddZ!dd Z"dS )    )ValidationError)Form)BooleanFieldIntegerField)	ErrorList)HiddenInputNumberInput)cached_property)	html_safe)	mark_safe)gettext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  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   base_fieldsTOTAL_FORM_COUNTINITIAL_FORM_COUNTMIN_NUM_FORM_COUNTMAX_NUM_FORM_COUNTsuper__init__)selfargskwargs)	__class__ 9/usr/lib/python3.6/site-packages/django/forms/formsets.pyr   "   s
    zManagementForm.__init__)__name__
__module____qualname____doc__r   __classcell__r    r    )r   r!   r      s   r   c               @   sl  e Zd ZdZeZddddde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d.d/ Zd0d1 Z d2d3 Z!d4d5 Z"d6d7 Z#d8d9 Z$d:d; Z%d<d= Z&d>d? Z'd@dA Z(edBdC Z)dDdE Z*dFdG Z+dHdI Z,dS )Jr   z;
    A collection of instances of the same Form class.
    Nzid_%sc             C   s`   |d k	p|d k	| _ |p| j | _|| _|p,i | _|p6i | _|| _|pFi | _|| _d | _	d | _
d S )N)is_boundget_default_prefixprefixauto_iddatafilesinitialform_kwargserror_class_errors_non_form_errors)r   r+   r,   r*   r)   r-   r/   r.   r    r    r!   r   4   s    


zBaseFormSet.__init__c             C   s   | j  S )N)as_table)r   r    r    r!   __str__A   s    zBaseFormSet.__str__c             C   s
   t | jS )z5Yield the forms in the order they should be rendered.)iterforms)r   r    r    r!   __iter__D   s    zBaseFormSet.__iter__c             C   s
   | j | S )zAReturn the form at the given index, based on the rendering order.)r5   )r   indexr    r    r!   __getitem__H   s    zBaseFormSet.__getitem__c             C   s
   t | jS )N)lenr5   )r   r    r    r!   __len__L   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    )r   r    r    r!   __bool__O   s    zBaseFormSet.__bool__c             C   sf   | j r4t| j| j| jd}|j sbttdddn.t| j| jt| j	 t
| j t| jt| jid}|S )z4Return the ManagementForm instance for this FormSet.)r*   r)   z8ManagementForm data is missing or has been tampered withZmissing_management_form)code)r*   r)   r-   )r'   r   r+   r*   r)   is_validr   _r   total_form_countr   initial_form_countr   min_numr   max_num)r   formr    r    r!   management_formV   s    

zBaseFormSet.management_formc             C   sx   | j rt| jjt | jS | j }t|| j| j	 }|| j
  koHdkn  rT|}n || j
  kohdkn  rt| j
}|S )z1Return the total number of forms in this FormSet.r   )r'   minrD   cleaned_datar   absolute_maxr@   maxrA   extrarB   )r   initial_formsZtotal_formsr    r    r!   r?   i   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'   rD   rF   r   r-   r9   )r   rJ   r    r    r!   r@   |   s    zBaseFormSet.initial_form_countc                s    fddt  j D S )z+Instantiate forms at first property access.c                s    g | ]} j |f j|qS r    )_construct_formget_form_kwargs).0i)r   r    r!   
<listcomp>   s   z%BaseFormSet.forms.<locals>.<listcomp>)ranger?   )r   r    )r   r!   r5      s    
zBaseFormSet.formsc             C   s
   | j 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.
        )r.   copy)r   r7   r    r    r!   rL      s    zBaseFormSet.get_form_kwargsc             K   s   | j | j|| jdd}| jr2| j|d< | j|d< | jrhd|krhy| j| |d< W n tk
rf   Y nX || j kr|| j	krd|d< |j
| | jf |}| j|| |S )z;Instantiate and return the i-th form instance in a formset.F)r*   r)   r/   use_required_attributer+   r,   r-   Tempty_permitted)r*   
add_prefixr/   r'   r+   r,   r-   
IndexErrorr@   rA   updaterC   
add_fields)r   rN   r   defaultsrC   r    r    r!   rK      s$    


zBaseFormSet._construct_formc             C   s   | j d| j  S )z7Return a list of all the initial forms in this formset.N)r5   r@   )r   r    r    r!   rJ      s    zBaseFormSet.initial_formsc             C   s   | j | j d S )z5Return a list of all the extra forms in this formset.N)r5   r@   )r   r    r    r!   extra_forms   s    zBaseFormSet.extra_formsc             C   s8   | j f | j| jdddd| jd }| j|d  |S )NZ
__prefix__TF)r*   r)   rS   rR   )rC   r*   rT   rL   rW   )r   rC   r    r    r!   
empty_form   s    zBaseFormSet.empty_formc             C   s(   | j  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    )rF   )rM   rC   r    r    r!   rO      s    z,BaseFormSet.cleaned_data.<locals>.<listcomp>)r=   AttributeErrorr   r"   r5   )r   r    r    r!   rF      s    zBaseFormSet.cleaned_datac                s    j   s j rg S t dsvg  _xNtd j D ]<} j| }| j kr\|j  r\q6 j	|r6 jj
| q6W  fdd jD S )z:Return a list of forms that have been marked for deletion._deleted_form_indexesr   c                s   g | ]} j | qS r    )r5   )rM   rN   )r   r    r!   rO      s    z-BaseFormSet.deleted_forms.<locals>.<listcomp>)r=   
can_deletehasattrr\   rP   r?   r5   r@   has_changed_should_delete_formappend)r   rN   rC   r    )r   r!   deleted_forms   s    


zBaseFormSet.deleted_formsc                s    j   s j r"td jj t dsg  _x`td j D ]N} j	| }| j
 krh|j  rhqB jrz j|rzqB jj||jt f qBW d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'	_orderingr   c             S   s   | d d krdS d| d fS )N   r   )rd   r   r    )kr    r    r!   compare_ordering_key  s    z7BaseFormSet.ordered_forms.<locals>.compare_ordering_key)keyc                s   g | ]} j |d   qS )r   )r5   )rM   rN   )r   r    r!   rO     s    z-BaseFormSet.ordered_forms.<locals>.<listcomp>)r=   	can_orderr[   r   r"   r^   rc   rP   r?   r5   r@   r_   r]   r`   ra   rF   ORDERING_FIELD_NAMEsort)r   rN   rC   rf   r    )r   r!   ordered_forms   s    

zBaseFormSet.ordered_formsc             C   s   dS )NrC   r    )clsr    r    r!   r(   
  s    zBaseFormSet.get_default_prefixc             C   s   | j S )N)ordering_widget)rl   r    r    r!   get_ordering_widget  s    zBaseFormSet.get_ordering_widgetc             C   s   | j dkr| j  | 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)r1   
full_clean)r   r    r    r!   non_form_errors  s    
zBaseFormSet.non_form_errorsc             C   s   | j dkr| j  | j S )z:Return a list of form.errors for every form in self.forms.N)r0   ro   )r   r    r    r!   errors  s    
zBaseFormSet.errorsc             C   s    t | j 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 )N)r9   )rM   form_errorsr    r    r!   	<genexpr>&  s    z0BaseFormSet.total_error_count.<locals>.<genexpr>)r9   rp   sumrq   )r   r    r    r!   total_error_count#  s    
zBaseFormSet.total_error_countc             C   s   |j jtdS )z7Return whether or not the form was marked for deletion.F)rF   getDELETION_FIELD_NAME)r   rC   r    r    r!   r`   (  s    zBaseFormSet._should_delete_formc             C   sb   | j s
dS d}| j x>td| j D ],}| j| }| jrD| j|rDq$||j M }q$W |o`| j  S )z1Return True if every form in self.forms is valid.FTr   )	r'   rq   rP   r?   r5   r]   r`   r=   rp   )r   Zforms_validrN   rC   r    r    r!   r=   ,  s    
zBaseFormSet.is_validc             C   sR  g | _ | j | _d}| jsdS xbtd| j D ]P}| j| }|j  rZ|| j krZ|d7 }|j	}| j
rr| j|rrq.| j j| q.W y| jr| j t| j | jks| jjt | jkrttdd| j| j dd| jo| j t| j | | jk rttdd| j| j dd| j  W n2 tk
rL } z| j|j| _W Y dd}~X nX dS )	ze
        Clean all of self.data and populate self._errors and
        self._non_form_errors.
        r   Nrd   z Please submit %d or fewer forms.Ztoo_many_forms)r<   zPlease submit %d or more forms.Ztoo_few_forms)r0   r/   r1   r'   rP   r?   r5   r_   r@   rq   r]   r`   ra   validate_maxr9   rb   rB   rD   rF   r   rG   r   r   validate_minrA   clean
error_list)r   Zempty_forms_countrN   rC   rr   er    r    r!   ro   >  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    )r   r    r    r!   rz   h  s    zBaseFormSet.cleanc             C   s   t dd | D S )z5Return True if data in any form differs from initial.c             s   s   | ]}|j  V  qd S )N)r_   )rM   rC   r    r    r!   rs   s  s    z*BaseFormSet.has_changed.<locals>.<genexpr>)any)r   r    r    r!   r_   q  s    zBaseFormSet.has_changedc             C   sz   | j rZ|dk	r>|| j k r>ttd|d d| j d|jt< nttdd| j d|jt< | jrvttddd|jt	< dS )	z8A hook for adding extra fields on to each form instance.NZOrderrd   F)labelr-   r   r   )r~   r   r   Delete)r~   r   )
rh   r@   r   r>   rn   fieldsri   r]   r   rw   )r   rC   r7   r    r    r!   rW   u  s    zBaseFormSet.add_fieldsc             C   s   d| j |f S )Nz%s-%s)r)   )r   r7   r    r    r!   rT     s    zBaseFormSet.add_prefixc             C   s"   | j r| j d j S | jj S dS )zv
        Return True if the formset needs to be multipart, i.e. it
        has FileInput, or False otherwise.
        r   N)r5   is_multipartrZ   )r   r    r    r!   r     s    zBaseFormSet.is_multipartc             C   s   | j r| j d jS | jjS d S )Nr   )r5   mediarZ   )r   r    r    r!   r     s    zBaseFormSet.mediac             C   s*   dj dd | D }tt| jd | S )zLReturn this formset rendered as HTML <tr>s -- excluding the <table></table>. c             s   s   | ]}|j  V  qd S )N)r2   )rM   rC   r    r    r!   rs     s    z'BaseFormSet.as_table.<locals>.<genexpr>
)joinr   strrD   )r   r5   r    r    r!   r2     s    zBaseFormSet.as_tablec             C   s*   dj dd | D }tt| jd | S )z*Return this formset rendered as HTML <p>s.r   c             s   s   | ]}|j  V  qd S )N)as_p)rM   rC   r    r    r!   rs     s    z#BaseFormSet.as_p.<locals>.<genexpr>r   )r   r   r   rD   )r   r5   r    r    r!   r     s    zBaseFormSet.as_pc             C   s*   dj dd | D }tt| jd | S )z+Return this formset rendered as HTML <li>s.r   c             s   s   | ]}|j  V  qd S )N)as_ul)rM   rC   r    r    r!   rs     s    z$BaseFormSet.as_ul.<locals>.<genexpr>r   )r   r   r   rD   )r   r5   r    r    r!   r     s    zBaseFormSet.as_ul)-r"   r#   r$   r%   r   rm   r   r   r3   r6   r8   r:   r;   r	   rD   r?   r@   r5   rL   rK   propertyrJ   rY   rZ   rF   rb   rk   classmethodr(   rn   rp   rq   ru   r`   r=   ro   rz   r_   rW   rT   r   r   r2   r   r   r    r    r    r!   r   -   sL   				&
*	
	rd   FNc	          
   C   sL   |dkrt }|dkrt}|t }	| ||||||	||d	}
t| jd |f|
S )z*Return a FormSet for the given form class.N)	rC   rI   rh   r]   rA   rB   rG   ry   rx   ZFormSet)DEFAULT_MIN_NUMDEFAULT_MAX_NUMtyper"   )rC   formsetrI   rh   r]   rB   rx   rA   ry   rG   attrsr    r    r!   r     s    c             C   s"   d}x| D ]}||j  M }q
W |S )z8Validate every formset and return True if all are valid.T)r=   )Zformsetsvalidr   r    r    r!   r     s    
)r   r   r   )#django.core.exceptionsr   Zdjango.formsr   django.forms.fieldsr   r   django.forms.utilsr   django.forms.widgetsr   r   django.utils.functionalr	   django.utils.htmlr
   django.utils.safestringr   django.utils.translationr   r>   r   __all__r   r   r   r   ri   rw   r   r   r   r   r   r   r    r    r    r!   <module>   s4      