a
    ùÜEbð7  ã                   @   s‚   d dl 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 d dlmZmZmZmZ G dd	„ d	ƒZG d
d„ deƒZdS )é    N)ÚNoReverseMatchÚreverse)Ú	mark_safe)ÚFormHelpersException)ÚLayout)ÚLayoutSlice)ÚTEMPLATE_PACKÚflatattÚlist_differenceÚrender_fieldc                   @   s\   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ ZdS )ÚDynamicLayoutHandlerc                 C   s   | j d u rtdƒ‚d S )Nz+You need to set a layout in your FormHelper)Úlayoutr   ©Úself© r   úS/home/ja/django-apps/lartica_env/lib/python3.9/site-packages/crispy_forms/helper.pyÚ_check_layout   s    
z"DynamicLayoutHandler._check_layoutc                 C   s   |   ¡  | jd u rtdƒ‚d S )Nz3You need to pass a form instance to your FormHelper)r   Úformr   r   r   r   r   Ú_check_layout_and_form   s    
z+DynamicLayoutHandler._check_layout_and_formc                 C   s$   |   ¡  t| jtdt| jjƒdƒƒS )zD
        Returns all layout objects of first level of depth
        r   é   )r   r   r   ÚsliceÚlenÚfieldsr   r   r   r   Úall   s    zDynamicLayoutHandler.allc                 O   s>   |   ¡  | dd¡}| dd¡}| jj|||d�}t| j|ƒS )zX
        Returns a LayoutSlice pointing to layout objects of type `LayoutClass`
        Ú	max_levelr   ÚgreedyF)r   r   )r   Úpopr   Zget_layout_objectsr   )r   ZLayoutClassesÚkwargsr   r   Zfiltered_layout_objectsr   r   r   Úfilter   s
    zDynamicLayoutHandler.filterc                 C   sN   |   ¡  | j ¡ }g }|D ]&}t| jj|d  j|ƒr| |¡ qt| j|ƒS )zX
        Returns a LayoutSlice pointing to fields with widgets of `widget_type`
        r   ©	r   r   Úget_field_namesÚ
isinstancer   r   ÚwidgetÚappendr   ©r   Zwidget_typeÚlayout_field_namesZfiltered_fieldsÚpointerr   r   r   Úfilter_by_widget(   s    
z%DynamicLayoutHandler.filter_by_widgetc                 C   sN   |   ¡  | j ¡ }g }|D ]&}t| jj|d  j|ƒs| |¡ qt| j|ƒS )zb
        Returns a LayoutSlice pointing to fields with widgets NOT matching `widget_type`
        r   r   r$   r   r   r   Úexclude_by_widget7   s    
z&DynamicLayoutHandler.exclude_by_widgetc                 C   sx   t |tƒrlt| |ƒrt| |ƒS |  ¡  | j ¡ }g }|D ]&}t|ƒdkr8|d |kr8| |¡ q8t	| j|ƒS t	| j|ƒS )z{
        Return a LayoutSlice that makes changes affect the current instance of the layout
        and not a copy.
        é   r   )
r!   ÚstrÚhasattrÚgetattrr   r   r    r   r#   r   )r   Úkeyr%   Zfiltered_fieldr&   r   r   r   Ú__getitem__F   s    



z DynamicLayoutHandler.__getitem__c                 C   s   || j |< d S ©N©r   )r   r-   Úvaluer   r   r   Ú__setitem___   s    z DynamicLayoutHandler.__setitem__c                 C   s   | j j|= d S r/   )r   r   )r   r-   r   r   r   Ú__delitem__b   s    z DynamicLayoutHandler.__delitem__c                 C   s   | j d urt| j jƒS dS d S )Nr   )r   r   r   r   r   r   r   Ú__len__e   s    
zDynamicLayoutHandler.__len__N)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r'   r(   r.   r2   r3   r4   r   r   r   r   r      s   r   c                   @   s4  e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZd#dd	„Zd
d„ Ze dd„ ƒZ!e!j"dd„ ƒZ!e dd„ ƒZ#e#j"dd„ ƒZ#e dd„ ƒZ$e$j"dd„ ƒZ$e dd„ ƒZ%e%j"dd„ ƒZ%e dd„ ƒZ&e&j"dd„ ƒZ&dd„ Z'dd„ Z(e)fdd „Z*e)fd!d"„Z+dS )$Ú
FormHelperah  
    This class controls the form rendering behavior of the form passed to
    the `{% crispy %}` tag. For doing so you will need to set its attributes
    and pass the corresponding helper object to the tag::

        {% crispy form form.helper %}

    Let's see what attributes you can set and what form behaviors they apply to:

        **form_method**: Specifies form method attribute.
            You can set it to 'POST' or 'GET'. Defaults to 'POST'

        **form_action**: Applied to the form action attribute:
            - Can be a named url in your URLconf that can be executed via the `{% url %}` template tag.             Example: 'show_my_profile'. In your URLconf you could have something like::

                path('show/profile/', 'show_my_profile_view', name = 'show_my_profile')

            - It can simply point to a URL '/whatever/blabla/'.

        **form_id**: Generates a form id for dom identification.
            If no id provided then no id attribute is created on the form.

        **form_class**: String containing separated CSS classes to be applied
            to form class attribute. The form will always have by default
            'uniForm' class.

        **form_group_wrapper_class**: String containing separated CSS classes to be applied
            to each row of inputs.

        **form_tag**: It specifies if <form></form> tags should be rendered when using a Layout.
            If set to False it renders the form without the <form></form> tags. Defaults to True.

        **form_error_title**: If a form has `non_field_errors` to display, they
            are rendered in a div. You can set title's div with this attribute.
            Example: "Oooops!" or "Form Errors"

        **formset_error_title**: If a formset has `non_form_errors` to display, they
            are rendered in a div. You can set title's div with this attribute.

        **form_style**: Uni-form has two built in different form styles. You can choose
            your favorite. This can be set to "default" or "inline". Defaults to "default".

        **include_media**: Whether to automatically include form media. Set to False if
            you want to manually include form media outside the form. Defaults to True.

    Public Methods:

        **add_input(input)**: You can add input buttons using this method. Inputs
            added using this method will be rendered at the end of the form/formset.

        **add_layout(layout)**: You can add a `Layout` object to `FormHelper`. The Layout
            specifies in a simple, clean and DRY way how the form fields should be rendered.
            You can wrap fields, order them, customize pretty much anything in the form.

    Best way to add a helper to a form is adding a property named helper to the form
    that returns customized `FormHelper` object::

        from crispy_forms.helper import FormHelper
        from crispy_forms.layout import Submit

        class MyForm(forms.Form):
            title = forms.CharField(_("Title"))

            @property
            def helper(self):
                helper = FormHelper()
                helper.form_id = 'this-form-rocks'
                helper.form_class = 'search'
                helper.add_input(Submit('save', 'save'))
                [...]
                return helper

    You can use it in a template doing::

        {% load crispy_forms_tags %}
        {% crispy form %}
    ÚpostÚ ÚdefaultNTFc                 C   s*   i | _ g | _|d ur&|| _|  |¡| _d S r/   )ÚattrsÚinputsr   Úbuild_default_layoutr   ©r   r   r   r   r   Ú__init__×   s
    zFormHelper.__init__c                 C   s   t |j ¡ Ž S r/   )r   r   Úkeysr?   r   r   r   r>   ß   s    zFormHelper.build_default_layoutc                 C   s   | j S r/   )Ú_form_methodr   r   r   r   Úform_methodâ   s    zFormHelper.form_methodc                 C   s"   |  ¡ dvrtdƒ‚|  ¡ | _d S )N)Úgetr9   zSOnly GET and POST are valid in the                     form_method helper attribute)Úlowerr   rB   )r   Úmethodr   r   r   rC   æ   s
    ÿc                 C   s*   zt | jƒW S  ty$   | j Y S 0 d S r/   )r   Ú_form_actionr   r   r   r   r   Úform_actionð   s    zFormHelper.form_actionc                 C   s
   || _ d S r/   )rG   )r   Úactionr   r   r   rH   ÷   s    c                 C   s    | j dkrdS | j dkrdS d S )Nr;   r:   ÚinlineZinlineLabels)Ú_form_styler   r   r   r   Ú
form_styleû   s    

zFormHelper.form_stylec                 C   s"   |  ¡ dvrtdƒ‚|  ¡ | _d S )N)r;   rJ   zXOnly default and inline are valid in the                     form_style helper attribute)rE   r   rK   )r   Ústyler   r   r   rL     s
    ÿc                 C   s   | j S r/   )Ú_help_text_inliner   r   r   r   Úhelp_text_inline  s    zFormHelper.help_text_inlinec                 C   s   || _ | | _d S r/   )rN   Ú_error_text_inline©r   Úflagr   r   r   rO     s    c                 C   s   | j S r/   )rP   r   r   r   r   Úerror_text_inline  s    zFormHelper.error_text_inlinec                 C   s   || _ | | _d S r/   )rP   rN   rQ   r   r   r   rS     s    c                 C   s   | j  |¡ d S r/   )r=   r#   )r   Zinput_objectr   r   r   Ú	add_input  s    zFormHelper.add_inputc                 C   s
   || _ d S r/   r0   )r   r   r   r   r   Ú
add_layout"  s    zFormHelper.add_layoutc              	   C   sª   t ƒ |_| j|_| jj|| j||d�}| js8| js8| j	r¢t
|j ¡ ƒ}t||jƒ}|D ]J}| jsˆ| jrt|j| jjsˆ| j	rV|j| jjrV|t||| j||d�7 }qVt|ƒS )zB
        Returns safe html of the rendering of the layout
        )Útemplate_pack)ÚsetZrendered_fieldsÚfield_templateZcrispy_field_templater   ÚrenderrL   Úrender_unmentioned_fieldsÚrender_hidden_fieldsÚrender_required_fieldsÚtupler   rA   r
   r"   Z	is_hiddenZis_requiredr   r   )r   r   ÚcontextrV   Úhtmlr   Zleft_fields_to_renderÚfieldr   r   r   Úrender_layout%  s&    ÿþþýýzFormHelper.render_layoutc                    s  | j | j| j| jpd| | j ¡ | j| j| j ¡ | j	| j
| j| j| j| jdœ}|dkr’d| j ¡ v r¾t d| j¡}|r¾d‰ ‡ fdd„|D ƒ|d	< n,t d
| j¡}|r¾d‰ ‡ fdd„|D ƒ|d	< i |d< | jrÚ| j ¡ |d< | jrò| j ¡ |d d< | j�r| j ¡ |d d< | j�rJ|dk�r6d| j ¡  |d d< n| j ¡ |d d< n$|dk�rn| j dd¡d |d d< | j�r„| j|d d< t|d ƒ|d< | j�r¦| j|d< | j�r¼| j ¡ |d< | j�rÒ| j ¡ |d< | j ¡ D ]2\}}||v�rÜ|dv�rÜ| d¡�sÜ|||< �qÜ|S )zD
        Used by crispy_forms_tags to get helper attributes
        z%s/field.html)Údisable_csrfrS   Úfield_classrX   rC   Úform_show_errorsÚform_show_labelsrL   Úform_tagrO   Úhtml5_requiredÚinclude_mediaÚlabel_classÚuse_custom_controlZ
bootstrap4zform-horizontalzcol(-(xl|lg|md|sm))?-(\d+)zoffset%s-%sc                    s    g | ]}ˆ |d  |d f ‘qS )r   éÿÿÿÿr   ©Ú.0Úm©Zoffset_patternr   r   Ú
<listcomp>W  s   z-FormHelper.get_attributes.<locals>.<listcomp>Zbootstrap_checkbox_offsetszcol-(lg|md|sm|xs)-(\d+)zcol-%s-offset-%sc                    s   g | ]}ˆ | ‘qS r   r   rl   ro   r   r   rp   ^  ó    r<   rI   ÚidZuni_formz
uniForm %sÚclassr:   z uniFormÚform_group_wrapper_classZ
flat_attrsr=   Úform_error_titleÚformset_error_title)r   r=   Ú_) rb   rS   rc   rX   rC   Ústriprd   re   rL   rf   rO   rg   rh   ri   rj   Ú
form_classÚsplitÚreÚfindallr<   ÚcopyrH   Úform_idrD   rt   r	   r=   ru   rv   Ú__dict__ÚitemsÚ
startswith)r   rV   r€   Zbootstrap_size_matchZattribute_namer1   r   ro   r   Úget_attributes=  st    ò
ÿ


ÿþýzFormHelper.get_attributes)N),r5   r6   r7   Ú__doc__rB   rG   rK   r   r~   ry   rt   r   rf   ru   rv   rd   rZ   r[   r\   rN   rP   rg   re   ÚtemplaterX   rb   rj   ri   rc   rh   r@   r>   ÚpropertyrC   ÚsetterrH   rL   rO   rS   rT   rU   r   ra   r‚   r   r   r   r   r8   l   sj   O


	



	



r8   )r{   Zdjango.urlsr   r   Zdjango.utils.safestringr   Zcrispy_forms.exceptionsr   Zcrispy_forms.layoutr   Zcrispy_forms.layout_slicer   Zcrispy_forms.utilsr   r	   r
   r   r   r8   r   r   r   r   Ú<module>   s   `