
    恕f4                        d Z 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mZmZ dd
lmZ ddlmZmZmZ ddlmZmZ ddlmZ 	 ddlmZ dZ G d de      Z G d de      Z  G d de       Z! G d de      Z" G d de#      Z$ G d de      Z% G d de      Z& G d d e      Z'd! Z(d" Z)d# Z*y# e	$ r	 ddl
mZ Y w xY w# e	$ r dZY |w xY w)$z5
    Useful form fields for use with SQLAlchemy ORM.
    N)SelectFieldBaseStringField)ValidationError)_unset_value)unset_value   )get_primary_key)	text_typestring_types	iteritems)CheckboxListInput)FormOptsBaseFormSelect2Widget)InlineFieldListInlineModelFormField)lazy_gettext)identity_keyTFc                   n     e Zd ZdZ e       Z	 	 	 d	 fd	Zd Zd Z e	ee      Z
d Zd Zd Zd Z xZS )
QuerySelectFielda  
    Will display a select drop-down field to choose between ORM results in a
    sqlalchemy `Query`.  The `data` property actually will store/keep an ORM
    model instance, not the ID. Submitting a choice which is not in the query
    will result in a validation error.

    This field only works for queries on models whose primary key column(s)
    have a consistent string representation. This means it mostly only works
    for those composed of string, unicode, and integer types. For the most
    part, the primary keys will be auto-detected from the model, alternately
    pass a one-argument callable to `get_pk` which can return a unique
    comparable key.

    The `query` property on the field can be set from within a view to assign
    a query per-instance to the field. If the property is not set, the
    `query_factory` callable passed to the field constructor will be called to
    obtain a query.

    Specify `get_label` to customize the label associated with each option. If
    a string, this is the name of an attribute on the model object to use as
    the label text. If a one-argument callable, this callable will be passed
    model instance and expected to return the label text. Otherwise, the model
    object's `__str__` or `__unicode__` will be used.

    If `allow_blank` is set to `True`, then a blank choice will be added to the
    top of the list. Selecting this choice will result in the `data` property
    being `None`. The label for this blank choice can be set by specifying the
    `blank_text` parameter.
    c                 <   t        t        | 
  ||fi | || _        |t        st        d      t        | _        n|| _        |	d | _        n2t        |t              rt        j                  |      | _        n|| _        || _        || _        d | _        d | _        y )Nz;The sqlalchemy identity_key function could not be imported.c                     | S N )xs    ^/var/www/feuerwehr-webapp/venv/lib/python3.12/site-packages/flask_admin/contrib/sqla/fields.py<lambda>z+QuerySelectField.__init__.<locals>.<lambda>J   s    q     )superr   __init__query_factoryhas_identity_key	Exceptionget_pk_from_identityget_pk	get_label
isinstancer   operator
attrgetterallow_blank
blank_textquery_object_list)
selflabel
validatorsr!   r%   r&   r*   r+   kwargs	__class__s
            r   r    zQuerySelectField.__init__<   s     	.ujKFK*># ^__.DK DK(DN	<0%00;DN&DN&$
 r   c                     | j                   E| j                         D ]2  \  }}|| j                   k(  s| j                  |        | j                  S  | j                  S r   )	_formdata_get_object_list	_set_data_datar.   pkobjs      r   	_get_datazQuerySelectField._get_dataU   sY    >>%002 C'NN3'zz	 zzr   c                      || _         d | _        y r   r7   r4   r.   datas     r   r6   zQuerySelectField._set_data]       
r   c                     | j                   P| j                  xs | j                         }| j                  }|D cg c]  }t	         ||            |f c}| _         | j                   S c c}w r   )r-   r,   r!   r%   r
   )r.   r,   r%   r:   s       r   r5   z!QuerySelectField._get_object_listc   sa    $JJ6$"4"4"6E[[FJO P3)F3K"8#!> PD    !Qs   A)c              #      K   | j                   rd| j                  | j                  d u f | j                         D ](  \  }}|| j	                  |      || j                  k(  f * y w)N__None)r*   r+   r?   r5   r&   r8   s      r   iter_choiceszQuerySelectField.iter_choicesj   sd     dootyyD/@AA,,. 	>GBt~~c*C499,<==	>s   A&A(c                 d    |r.| j                   r|d   dk(  rd | _        y d | _        |d   | _        y y )Nr   rC   )r*   r?   r7   r4   r.   	valuelists     r   process_formdataz!QuerySelectField.process_formdataq   s7    IaLI$= 	!
!*1 r   c                     | j                   r| j                  C| j                         D ]  \  }}| j                  |k(  s y  t        | j	                  d            y )NNot a valid choice)r*   r?   r5   r   gettext)r.   formr9   r:   s       r   pre_validatezQuerySelectField.pre_validatey   s]    499#8002 KC99#K &dll3H&IJJ $9r   )NNNNNF )__name__
__module____qualname____doc__r   widgetr    r;   r6   propertyr?   r5   rD   rH   rM   __classcell__r2   s   @r   r   r      sL    : _FBF:?!2 Iy)D!>.Kr   r   c                   f     e Zd ZdZ ed      Zd
 fd	Zd Zd Z e	ee      Z
d Zd Zd	 Z xZS )QuerySelectMultipleFieldal  
    Very similar to QuerySelectField with the difference that this will
    display a multiple select. The data property will hold a list with ORM
    model instances and will be an empty list when no value is selected.

    If any of the items in the data list or submitted form data cannot be
    found in the query, this will result in a validation error.
    T)multiplec                 J    |g }t        t        | 
  ||fd|i| d| _        y )NdefaultF)r   rX   r    _invalid_formdata)r.   r/   r0   r[   r1   r2   s        r   r    z!QuerySelectMultipleField.__init__   s3    ?G&6ujdRYd]cd!&r   c                     | j                   }|_g }| j                         D ]0  \  }}|s n)||v s|j                  |       |j                  |       2 |rd| _        | j                  |       | j                  S )NT)r4   r5   removeappendr\   r6   r7   )r.   formdatar?   r9   r:   s        r   r;   z"QuerySelectMultipleField._get_data   sz    >>D002 %C8^OOB'KK$% )-&NN4 zzr   c                      || _         d | _        y r   r=   r>   s     r   r6   z"QuerySelectMultipleField._set_data   r@   r   c              #      K   | j                         D ]'  \  }}|| j                  |      || j                  v f ) y wr   )r5   r&   r?   r8   s      r   rD   z%QuerySelectMultipleField.iter_choices   sA     ,,. 	>GBt~~c*C499,<==	>s   <>c                 $    t        |      | _        y r   )setr4   rF   s     r   rH   z)QuerySelectMultipleField.process_formdata   s    Yr   c                    | j                   rt        | j                  d            | j                  rPt	        d | j                         D              }| j                  D ]   }||vst        | j                  d             y y )NrJ   c              3   &   K   | ]	  }|d      yw)r   Nr   .0r   s     r   	<genexpr>z8QuerySelectMultipleField.pre_validate.<locals>.<genexpr>   s     BQAaDBs   )r\   r   rK   r?   listr5   )r.   rL   obj_listvs       r   rM   z%QuerySelectMultipleField.pre_validate   sw    !!!$,,/D"EFFYYB$*?*?*ABBHYY OH$)$,,7L*MNNO r   )NNN)rO   rP   rQ   rR   r   rS   r    r;   r6   rT   r?   rD   rH   rM   rU   rV   s   @r   rX   rX      sA     D)F' Iy)D>(Or   rX   c                       e Zd ZdZ e       Zy)CheckboxListFielda  
    Alternative field for many-to-many relationships.

    Can be used instead of `QuerySelectMultipleField`.
    Appears as the list of checkboxes.
    Example::

        class MyView(ModelView):
            form_columns = (
                'languages',
            )
            form_args = {
                'languages': {
                    'query_factory': Language.query,
                },
            }
            form_overrides = {
                'languages': CheckboxListField,
            }
    N)rO   rP   rQ   rR   r   rS   r   r   r   rn   rn      s    (  Fr   rn   c                   H    e Zd ZdZ e ed            Z e ed            Zy)
HstoreFormzB Form used in InlineFormField/InlineHstoreList for HSTORE columns KeyValueN)rO   rP   rQ   rR   r   r   keyvaluer   r   r   rp   rp      s#    L
l5)
*CW-.Er   rp   c                       e Zd ZdZddZy)KeyValuezk Used by InlineHstoreList to simulate a key and a value field instead of
        the single HSTORE column. Nc                      || _         || _        y r   )rs   rt   )r.   rs   rt   s      r   r    zKeyValue.__init__   s    
r   )NN)rO   rP   rQ   rR   r    r   r   r   rv   rv      s    &r   rv   c                   ,     e Zd ZdZef fd	Zd Z xZS )InlineHstoreListzA Version of InlineFieldList for use with Postgres HSTORE columns c                     t        |t              r't        |      D cg c]  \  }}t        ||       }}}t        t
        |   ||       yc c}}w )z SQLAlchemy returns a dict for HSTORE columns, but WTForms cannot
            process a dict. This overrides `process` to convert the dict
            returned by SQLAlchemy to a list of classes before processing. N)r'   dictr   rv   r   ry   process)r.   r`   r?   krl   r2   s        r   r|   zInlineHstoreList.process   sH     dD!/8?tq!HQN?D?-h= @s   Ac                 H   t        t        d      t        fi       }i }| j                  D ]i  }| j	                  |      r |       }t               |_        |j                  |d       |j                  j                  ||j                  j                  <   k t        |||       y)zA Combines each FormField key/value into a dictionary for storage _faker?   N)typestrobjectentriesshould_deleterv   r?   populate_objrt   rs   setattr)r.   r:   namer   output
form_fieldfake_objs          r   r   zInlineHstoreList.populate_obj   s    S\F:r2,, 	@J%%j1 7 (
''&9,4MM,?,?x}}(()	@ 	T6"r   )rO   rP   rQ   rR   r   r|   r   rU   rV   s   @r   ry   ry      s    K%0 >#r   ry   c                   4     e Zd ZdZeZ	  fdZd Zd Z xZ	S )InlineModelFormListz6
        Customized inline model form list field.
    c                    || _         || _        || _        || _        || _        t        |      | _        t        t        |dd      |j                        }| j                  || j                  |      }t        t        | 6  |fi | y)aa  
            Default constructor.

            :param form:
                Form for the related model
            :param session:
                SQLAlchemy session
            :param model:
                Related model
            :param prop:
                Related property name
            :param inline_view:
                Inline view
        form_widget_argsNwidget_args
form_rules)	form_opts)rL   sessionmodelpropinline_viewr	   _pkr   getattr_form_rulesform_field_typer   r   r    )
r.   rL   r   r   r   r   r1   r   r   r2   s
            r   r    zInlineModelFormList.__init__  s     	
	&"5) >PRV)W(3(?(?A	 ))$I)N
!41*GGr   c                 &    |j                         d uS r   )r%   )r.   fields     r   display_row_controlsz(InlineModelFormList.display_row_controls"  s    ||~T))r   c                     t        ||d       }|y t         fd|D              } j                  D ]  }t        |      }||v}|s2||   } j	                  |      r= j
                  j                  |       F j                         }|j                  |       |j                  |d         j                  j                  |||        y )Nc              3   N   K   | ]  }t        |j                        |f  y wr   )
get_obj_pkr   )rh   rl   r.   s     r   ri   z3InlineModelFormList.populate_obj.<locals>.<genexpr>,  s!     Cqz!TXX.2Cs   "%)r   r{   r   get_field_idr   r   deleter   r_   r   r   _on_model_change)	r.   r:   r   valuespk_mapr   field_id
is_createdr   s	   `        r   r   z InlineModelFormList.populate_obj%  s    dD)> CFCC \\ 	HE#E*H!/Jx(%%e,LL''.

e$ud+--eUJG!	Hr   )
rO   rP   rQ   rR   r   r   r    r   r   rU   rV   s   @r   r   r      s%     +OH>*Hr   r   c                   4     e Zd Z fdZed        Zd Z xZS )InlineModelOneToOneFieldc                     || _         || _        || _        || _        || _        t        |      | _        t        t        |dd       |j                        }t        | ,  || j                  fd|i| y )Nr   r   r   )rL   r   r   r   r   r	   r   r   r   r   r   r    )	r.   rL   r   r   r   r   r1   r   r2   s	           r   r    z!InlineModelOneToOneField.__init__C  st    	
	&"5) -?F"..
	 	txxG9GGr   c                 0    | yt        | t              r| syy)z:
        Check while installed fields is not null
        TF)r'   r   )r   s    r   _looks_emptyz%InlineModelOneToOneField._looks_emptyS  s    
 =eS!%r   c                    t        ||d       }d}d}|sd}| j                         }t        | j                  j                        D ]G  \  }}|| j
                  k7  r|j                  ||       |s*| j                  |j                        rFd}I |ry t        |||       | j                  j                  | j                  ||       y )NFT)r   r   r   rL   _fieldsr   r   r   r?   r   r   on_model_change)r.   r   
field_nameinline_modelr   form_is_emptyr   r   s           r   r   z%InlineModelOneToOneField.populate_obj`  s    uj$7
J::<L %TYY%6%67 	&KD%txx""<6T%6%6uzz%B %	&  	z<0 	((E:Fr   )rO   rP   rQ   r    staticmethodr   r   rU   rV   s   @r   r   r   B  s#    H  
 
Gr   r   c                 P    t        |       d   }dj                  d |D              S )N)instancer   :c              3   2   K   | ]  }t        |        y wr   r
   rg   s     r   ri   z'get_pk_from_identity.<locals>.<genexpr>  s     /aYq\/   )r   join)r:   rs   s     r   r$   r$   |  s&    

$Q
'C99/3///r   c                 v     t        |t              rt         fd|D              S t        t         |            S )z:
    get and format pk from obj
    :rtype: text_type
    c              3   H   K   | ]  }t        t        |              y wr   )r
   r   )rh   r}   r:   s     r   ri   zget_obj_pk.<locals>.<genexpr>  s     <AYwsA/<s   ")r'   tupler
   r   )r:   r9   s   ` r   r   r     s2     "e<<<<WS"%&&r   c                 |    | j                         }t        |t              rt        d |D              S t        |      S )z<
    get and format id from field
    :rtype: text_type
    c              3   2   K   | ]  }t        |        y wr   r   )rh   _s     r   ri   zget_field_id.<locals>.<genexpr>  s     4aYq\4r   )r%   r'   r   r
   )r   r   s     r   r   r     s5    
 ||~H(E"48444Xr   )+rR   r(   wtforms.fieldsr   r   wtforms.validatorsr   r   r   ImportErrorwtforms.utilstoolsr	   flask_admin._compatr
   r   r    flask_admin.contrib.sqla.widgetsr   flask_admin.formr   r   r   flask_admin.model.fieldsr   r   flask_admin.babelr   sqlalchemy.orm.utilr   r"   r   rX   rn   rp   r   rv   ry   r   r   r$   r   r   r   r   r   <module>r      s     7 .*: # B B > > > J *0
cK cKL4O/ 4On!0 !0/ /v # #4FH/ FHR7G3 7Gt0	'	G  *)*  s#   B5 C 5CCCC