o
    e1                     @   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                   @   sd   e Zd Zdd Zdd Zdd Zddd	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   T/var/www/html/humari/django-venv/lib/python3.10/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.allr   F	max_levelgreedyc                G   s&   |    | jj|||d}t| j|S )zX
        Returns a LayoutSlice pointing to layout objects of type `LayoutClass`
        r   )r   r   get_layout_objectsr   )r   r   r   LayoutClassesfiltered_layout_objectsr   r   r   filter   s   zDynamicLayoutHandler.filterc                 C   sL   |    | j }g }|D ]}t| jj|j j|r|| qt	| j|S )zX
        Returns a LayoutSlice pointing to fields with widgets of `widget_type`
        
r   r   get_field_names
isinstancer   r   namewidgetappendr   r   widget_typelayout_field_namesfiltered_fieldspointerr   r   r   filter_by_widget&      

z%DynamicLayoutHandler.filter_by_widgetc                 C   sL   |    | j }g }|D ]}t| jj|j j|s|| qt	| j|S )zb
        Returns a LayoutSlice pointing to fields with widgets NOT matching `widget_type`
        r!   r'   r   r   r   exclude_by_widget5   r-   z&DynamicLayoutHandler.exclude_by_widgetc                 C   sj   t |tr/t| |rt| |S |   | j }g }|D ]}|j|kr(|| qt	| j|S t	| j|S )z{
        Return a LayoutSlice that makes changes affect the current instance of the layout
        and not a copy.
        )
r#   strhasattrgetattrr   r   r"   r$   r&   r   )r   keyr)   filtered_fieldr+   r   r   r   __getitem__D   s   





z DynamicLayoutHandler.__getitem__c                 C   s   || j |< d S Nr   )r   r2   valuer   r   r   __setitem__]      z DynamicLayoutHandler.__setitem__c                 C   s   | j j|= d S r5   )r   r   )r   r2   r   r   r   __delitem__`   r9   z DynamicLayoutHandler.__delitem__c                 C   s   | j d urt| j jS dS )Nr   )r   r   r   r   r   r   r   __len__c   s   
zDynamicLayoutHandler.__len__N)__name__
__module____qualname__r   r   r   r    r,   r.   r4   r8   r:   r;   r   r   r   r   r      s    	r   c                   @   s  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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#dd Z$dd Z%e&fddZ'e&fddZ(dS ) 
FormHelperaq  
    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.

        **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.

        **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 NTFc                 C   s.   i | _ g | _|d ur|| _| || _d S d S r5   )attrsinputsr   build_default_layoutr   r   r   r   r   r   __init__   s   zFormHelper.__init__c                 C   s   t |j  S r5   )r   r   keysrE   r   r   r   rD      r9   zFormHelper.build_default_layoutc                 C      | j S r5   )_form_methodr   r   r   r   form_method      zFormHelper.form_methodc                 C   s"   |  dvr
td|  | _d S )N)getr@   zSOnly GET and POST are valid in the                     form_method helper attribute)lowerr   rI   )r   methodr   r   r   rJ      s
   c                 C   s&   zt | jW S  ty   | j Y S w r5   )r   _form_actionr   r   r   r   r   form_action   s
   
zFormHelper.form_actionc                 C   
   || _ d S r5   )rO   )r   actionr   r   r   rP      s   
c                 C   rH   r5   )_help_text_inliner   r   r   r   help_text_inline   rK   zFormHelper.help_text_inlinec                 C      || _ | | _d S r5   )rS   _error_text_inliner   flagr   r   r   rT         c                 C   rH   r5   )rV   r   r   r   r   error_text_inline   rK   zFormHelper.error_text_inlinec                 C   rU   r5   )rV   rS   rW   r   r   r   rZ     rY   c                 C   s   | j | d S r5   )rC   r&   )r   input_objectr   r   r   	add_input  s   zFormHelper.add_inputc                 C   rQ   r5   r6   )r   r   r   r   r   
add_layout	  s   
zFormHelper.add_layoutc                 C   s   t  |_| j|_| jj|||d}| js| js| jrMt	|j
 }t||j}|D ]#}| jsB| jr8|j
| jjsB| jrL|j
| jjrL|t||||d7 }q)t|S )zB
        Returns safe html of the rendering of the layout
        )template_pack)setrendered_fieldsfield_templatecrispy_field_templater   renderrender_unmentioned_fieldsrender_hidden_fieldsrender_required_fieldstupler   rG   r
   r%   	is_hiddenis_requiredr   r   )r   r   contextr^   htmlr   left_fields_to_renderfieldr   r   r   render_layout  s(   zFormHelper.render_layoutc                    s  | j r| j  ni }| jr| j |d< | jr| j |d< | jr(| j |d< | jr0| j|d< i d|d| jd| jd| j	d	| j
pGd
| dt|d| j d| j d| jd| jd| jd| j d| jd| jd| jd| j}|dkrd| j v rtd| j}|rd  fdd|D |d< ntd| j}|rd  fdd|D |d< | jr| j|d < | j D ]\}}||vr|d!vr|d"s|||< q|S )#zD
        Used by crispy_forms_tags to get helper attributes
        rR   idclassform_group_wrapper_classrB   disable_csrfrZ   field_classra   z%s/field.html
flat_attrsform_error_titlerJ   form_show_errorsform_show_labelsform_tagformset_error_titlerT   include_medialabel_classuse_custom_control
bootstrap4zform-horizontalzcol(-(xl|lg|md|sm))?-(\d+)zoffset%s-%sc                    s    g | ]} |d  |d f qS )r   r   .0moffset_patternr   r   
<listcomp>J  s    z-FormHelper.get_attributes.<locals>.<listcomp>bootstrap_checkbox_offsetszcol-(lg|md|sm|xs)-(\d+)zcol-%s-offset-%sc                    s   g | ]} | qS r   r   r   r   r   r   r   Q  s    rC   )r   rC   _)rB   copyrP   stripform_id
form_classrq   rr   rZ   rs   ra   r	   ru   rJ   rv   rw   rx   ry   rT   rz   r{   r|   splitrefindallrC   __dict__items
startswith)r   r^   rB   r   bootstrap_size_matchattribute_namer7   r   r   r   get_attributes$  s   


	




zFormHelper.get_attributesr5   ))r<   r=   r>   __doc__rI   rO   r   r   r   rq   r   rx   ru   ry   rv   rd   re   rf   rS   rV   rw   templatera   rr   r|   r{   rs   rz   rF   rD   propertyrJ   setterrP   rT   rZ   r\   r]   r   rn   r   r   r   r   r   r?   j   s`    K


	





r?   )r   django.urlsr   r   django.utils.safestringr   crispy_forms.exceptionsr   crispy_forms.layoutr   crispy_forms.layout_slicer   crispy_forms.utilsr   r	   r
   r   r   r?   r   r   r   r   <module>   s    ^