
    恕fu                     f   d dl Z d dlZd dlZd dlmZ d dlmZmZ d dlm	Z	m
Z
 d dlmZ d dlmZmZ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 dlmZmZ d dlmZ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) d dl*m+Z+m,Z-m.Z. ddl/m0Z0 ddl1m2Z2  e jf                  d      Z4 G d de#      Z5y)    N)InstrumentedAttribute)manager_of_classinstance_state)
joinedloadaliased)desc)BooleanTablefuncor_)IntegrityError)cast)Unicode)current_appflash)string_types	text_type)gettextngettextlazy_gettext)is_relationship)BaseModelView)create_editable_list_form)action)ObsoleteAttr)formfilterstools   )DEFAULT_FORMATTERS)create_ajax_loaderzflask-admin.sqlac                       e Zd ZdZ eddd      Z	  eddd      Z	  edd	d
      Z	  eddd      Z	 dZ		 e
j                  Z	 e
j                  Z	  ej                          Z	 d
Z	 dZ	 eZdZ	 efZ	 dZ	 	 	 d3 fd	Zd4dZd5dZd Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d Z&d Z'd6dZ(d Z)d Z*d Z+d Z,d  Z-d! Z. fd"Z/d# Z0d$ Z1d% Z2d& Z3	 d7d'Z4d( Z5 fd)Z6d* Z7d+ Z8d, Z9d- Z: fd.Z; e<d/ e=d0       e=d1            d2        Z> xZ?S )8	ModelViewz
        SQLAlchemy model view

        Usage sample::

            admin = Admin()
            admin.add_view(ModelView(User, db.session))
    column_auto_select_relatedauto_select_relatedTcolumn_select_relatedlist_select_relatedNcolumn_display_all_relationslist_display_all_relationsFcolumn_searchable_listsearchable_columnsc                    || _         d| _        t               | _        t               | _        | j
                  i | _        t        t        | #  ||||||||	|
	       t        | j                        | _        | j                         | _        | j                  "t        d| j                  j                  z        | j                   s| j#                         | _        y| j                   | _        y)al  
            Constructor.

            :param model:
                Model class
            :param session:
                SQLAlchemy session
            :param name:
                View name. If not set, defaults to the model name
            :param category:
                Category name
            :param endpoint:
                Endpoint name. If not set, defaults to the model name
            :param url:
                Base URL. If not set, defaults to '/admin/' + endpoint
            :param menu_class_name:
                Optional class name for the menu item.
            :param menu_icon_type:
                Optional icon. Possible icon types:

                 - `flask_admin.consts.ICON_TYPE_GLYPH` - Bootstrap glyph icon
                 - `flask_admin.consts.ICON_TYPE_FONT_AWESOME` - Font Awesome icon
                 - `flask_admin.consts.ICON_TYPE_IMAGE` - Image relative to Flask static directory
                 - `flask_admin.consts.ICON_TYPE_IMAGE_URL` - Image with full URL
            :param menu_icon_value:
                Icon glyph name or URL, depending on `menu_icon_type` setting
        N)menu_class_namemenu_icon_typemenu_icon_valuez#Model %s does not have primary key.)session_search_fieldsdict_filter_joins_sortable_joinsform_choicessuperr#   __init__r   model_managerscaffold_pk_primary_key	Exception__name__column_select_related_listscaffold_auto_joins_auto_joins)selfr8   r0   namecategoryendpointurlstatic_folderr-   r.   r/   	__class__s              \/var/www/feuerwehr-webapp/venv/lib/python3.12/site-packages/flask_admin/contrib/sqla/view.pyr7   zModelView.__init__-  s    < "!V#v$ "Di'tXxm8G7E8G 	( 	I
 )4 !,,.$ADJJDWDWWXX ..#779D#>>D    c                 ^    || j                   }|j                  j                  j                  S )z<
            Return property iterator for the model
        )r8   _sa_class_managermapperiterate_propertiesrA   r8   s     rH   _get_model_iteratorzModelView._get_model_iteratorj  s*     =JJE&&--@@@rI   c                    d}|r|D ]  }||f}|j                  |      }||vrt        |t              s)t        |j                  j
                  j                        }|r|j                  n|j                  }	|| |	|      n |	||      }n)t        ||j                        }
| |	|
      n |	||
      }|||<   |} |||fS )a_  
            Apply join path to the query.

            :param query:
                Query to add joins to
            :param joins:
                List of current joins. Used to avoid joining on same relationship more than once
            :param path:
                Path to be joined
            :param fn:
                Join function
        N)get
isinstancer
   r   propertyrL   class_join	outerjoingetattrkey)rA   queryjoinspath
inner_joinlastitemrX   aliasfnprops              rH   _apply_path_joinszModelView._apply_path_joinss  s      !4(		#e#%dE2 '(<(<(C(C D'1uB|,1M4r%&tTXX6,1M4r%!&E#J%( eT!!rI   c                 @    t        j                  | j                        S )z
            Return the primary key name(s) from a model
            If model has single primary key, will return a string and tuple otherwise
        )r   get_primary_keyr8   rA   s    rH   r:   zModelView.scaffold_pk  s    
 $$TZZ00rI   c                     t        | j                  t              r(t        j                  fd| j                  D              S t        j
                  t        | j                              S )z
            Return the primary key value from a model object.
            If there are multiple primary keys, they're encoded into string representation.
        c              3   6   K   | ]  }t        |        y wN)rW   ).0attrr8   s     rH   	<genexpr>z)ModelView.get_pk_value.<locals>.<genexpr>  s     #WTGE4$8#Ws   )rR   r;   tupler   
iterencodeescaperW   rN   s    `rH   get_pk_valuezModelView.get_pk_value  sN    
 d''/###WTEVEV#WWW<<t/@/@ ABBrI   c                    g }| j                         D ]P  }t        |d      rB| j                  s|j                  j                  dk(  s6|j                  |j                         Rt        |d      s_t        |j                        dkD  rt        j                  | j                  j                  |j                        }t        |      dk(  rt        |      dkD  r1t        j                  d| j                  d|j                  d       |d   }n|j                  d   }|j                  r| j                   s|j"                  r6|j                  |j                         S |S )	z>
            Return a list of columns from the model.
        	direction	MANYTOONEcolumnsr   r   z,Can not convert multiple-column properties (.))rO   hasattrr(   rq   rB   appendrX   lenrs   r   filter_foreign_columnsr8   	__table__warningswarnforeign_keyscolumn_display_pkprimary_key)rA   rs   pfilteredcolumns        rH   scaffold_list_columnszModelView.scaffold_list_columns  s    ))+ 	&Aq+&448H8HK8WNN155)I&qyy>A%$;;DJJ<P<PRSR[R[\H8}) X* ^b^h^hjkjojo&pq %a[FYYq\F&&--&2D2Dquu%1	&4 rI   c                    t               }| j                         D ]l  }t        |d      st        |j                        dkD  r)|j                  d   }|j
                  rE| j                  s|j                  r^|||j                  <   n |S )zz
            Return a dictionary of sortable columns.
            Key is column name, value is sort column/field.
        rs   r   r   )	r2   rO   rv   rx   rs   r}   r~   r   rX   )rA   rs   r   r   s       rH   scaffold_sortable_columnsz#ModelView.scaffold_sortable_columns  s    
 &))+ 	(Aq)$qyy>A%1 &&--&2D2D!'!	($ rI   c                    t               | _        | j                  | j                         S t               }| j                  D ]G  }t	        |t
              rt	        |d   t
              rYg g }}|d   D ]G  }t        j                  | j                  |      \  }}|j                  |       |j                  |       I |d   }nZt        j                  | j                  |d         \  }}|d   }n.t        j                  | j                  |      \  }}t        |      }|r2t        |d   d      st	        |d   t              r|| j                  |<   n5|rt        dj                  |            t        |dd      |j                   }|||<   J |S )a2  
            Returns a dictionary of the sortable columns. Key is a model
            field name and value is sort column (for example - attribute).

            If `column_sortable_list` is set, will use it. Otherwise, will call
            `scaffold_sortable_columns` to get them from the model.
        Nr   r   rS   zFor sorting columns in a related table, column_sortable_list requires a string like '<relation name>.<column name>'. Failed on: {0}rX   )r2   r4   column_sortable_listr   rR   rl   r   get_field_with_pathr8   rw   r   rv   listr<   formatrW   rX   )	rA   resultcr   r[   r^   column_item	path_itemcolumn_names	            rH   get_sortable_columnszModelView.get_sortable_columns  s     $v$$,1133VF.. -a'!!A$.')2$%aD 3D5:5N5Ntzz[_5`2K"MM+6 KK	23 '(d','@'@QqT'R&'d#(#<#<TZZ#KLFD"+A,KWT!Wj9ZQQU=V8<D((5# %5 6<VAY@ @ vud3?&,jj '-{#;-> MrI   c                 x   |r|D cg c]	  }||vs| }}g }|D ]}  }	 t        j                  | j                  |      \  }}|rt        |      }n%t	        |dd      |j
                  }nt        |      }| j                  |      }|j                  ||f        |S c c}w # t        $ r t        |      }Y Cw xY w)a  
            Returns a list of tuples with the model field name and formatted
            field name.

            Overridden to handle special columns like InstrumentedAttribute.

            :param only_columns:
                List of columns to include in the results. If not set,
                `scaffold_list_columns` will generate the list from the model.
            :param excluded_columns:
                List of columns to exclude from the results.
        rX   N)	r   r   r8   r   rW   rX   AttributeErrorget_column_namerw   )	rA   only_columnsexcluded_columnsr   formatted_columnsr   r[   r   visible_names	            rH   get_column_nameszModelView.get_column_names  s     '3Q!q@P7PAQLQ 	BA+$88QG"+A,K vud3?&,jj&/l  //<L $$k<%@A-	B0 ! 7 R  " + (l	+s   	BBAB""B98B9c                    | j                   rg | _        | j                   D ]  }t        j                  | j                  |      \  }}|st        d|z        t        j                  | j                  |      rI|}t        |t              r|j                  d      d   |_
        | j                  j                  ||f       t        j                  |      D ]  }| j                  j                  ||f       !  t        | j                         S )z
            Initialize search. Returns `True` if search is supported for this
            view.

            For SQLAlchemy, this will initialize internal fields: list of
            column objects used for filtering, etc.
        z)Failed to find field for search field: %srt   )r*   r1   r   r   r8   r<   is_hybrid_propertyrR   r   splitrX   rw   get_columns_for_fieldbool)rA   rB   rj   rZ   r   s        rH   init_searchzModelView.init_searchC  s     &&"$D33 D#77

DIe#$ORV$VWW++DJJ=!F!$5%)ZZ_R%8
''..?"'"="=d"C D++22FE?CDD D//00rI   c                 Z   | j                   syg }| j                   D ]}  }t        |t              r@|j                  | j                  j                  |j                  |j                               S|j                  | j                  j                  ||              dj                  |      S )aa  
            Return search placeholder.

            For example, if set column_labels and column_searchable_list:

            class MyModelView(BaseModelView):
                column_labels = dict(name='Name', last_name='Last Name')
                column_searchable_list = ('name', 'last_name')

            placeholder is: "Name, Last Name"
        Nz, )r*   rR   r   rw   column_labelsrQ   rX   rU   )rA   placeholders
searchables      rH   search_placeholderzModelView.search_placeholder_  s     **55 	DJ*&;<##&&**:>>:>>JL ##&&**:zBD	D zz,''rI   c                    t        j                  | j                  |      \  }}|t        d|z        t	        |      rZg }| j                  |j                  j                  j                        D ]#  }t        |d      s|j                  d   }|j                  s|j                  r9| j                  |j                  j                  j                         d| j                  |j"                        }t%        |j$                        j&                  }| j(                  j+                  |||      }	|	s|j,                  }
|r|| j.                  |<   n0t        j0                  | j                  |
      r|
g| j.                  |<   |j3                  |	       & |S t        j4                  | j                  |      }|r,|}t7        |t8              rP|j;                  d      d   |_        n6t        j<                  |      }t?        |      dkD  rt        d	|z        |d   }d}t7        |t8              rd|v r|j;                  d      d   }|st        j0                  | j                  |j,                        r|| j@                  vr|rG|d| j                  |j,                  j                         d| j                  |j                         }n| j                  |j,                  j                         d| j                  |j                         }nt7        |t8              s&| j                  |j                  j"                        }nM| j@                  r|| j@                  v r| j@                  |   }n#| j                  |      }|jC                  dd      }t%        |j$                        j&                  }| j(                  j+                  |||| jD                  jG                  |      
      }	|}|r djI                  ||      }|	D ]	  }||_%         |r|| j.                  |<   |	S |sDt        j0                  | j                  |j,                        r|j,                  g| j.                  |<   |	S )z4
            Return list of enabled filters
        Nz#Failed to find field for filter: %srs   r   z / rt   r   r   z-Can not filter more than on one column for %s)optionsz{0}.{1})&r   r   r8   r<   r   rO   rS   rL   rT   rv   rs   r}   r   r   ra   targetrB   rX   typer=   filter_converterconverttabler3   	need_joinextendr   rR   r   r   r   rx   r   replacecolumn_choicesrQ   r   key_name)rA   rB   rj   rZ   r   r   r   r   	type_namefltr   r   rs   joined_column_namer   fs                   rH   scaffold_filterszModelView.scaffold_filtersz  s   
 //

DAe<ADHII 4 G--dmm.B.B.I.IJ ,1i(YYq\F**f.@.@ 040D0DTYYEUEUEZEZ0[040D0DQUU0K$ML !%V[[ 1 : :I//77	8>8DFC  & 9>D..v6"__TZZ?:?D..v6s+1,4 N!&!9!9$**d!K!dL1!%C!4FJ55d;w<!##$SVZ$Z[[  "&$-#+%)ZZ_Q%7" '5??4::v||+T 2 22%*,,V\\->->?,,V[[9$L ,,V\\->->?,,V[[9$L
 "$5#'#7#78I8I#JL))dd6H6H.H'+'9'9$'?'+';';D'A'3';';C'GV[[)22I''//++//5	 0 C H "$++,>G *A!)AJ* /4""8, J (EOODJJ,U06~""8,JrI   c                     t        |t        j                        r`|j                  }t        |t              rDt        j                  | j                  |j                        r|j                  g| j                  |<   |S rh   )
rR   sqla_filtersBaseSQLAFilterr   r   r   r   r8   r   r3   )rA   filterr   s      rH   handle_filterzModelView.handle_filter  sY    fl99:]]F 6#89OODJJ=.4ll^""6*rI   c           
      >   | j                  | j                  |       }t        j                  | j                  || j
                  | j                  | j                  | j                  | j                  | j                        }| j                  r| j                  |      }|S )z1
            Create form from the model.
        )
base_classonlyexclude
field_argsignore_hiddenextra_fields)model_form_converterr0   r   get_formr8   form_base_classform_columnsform_excluded_columns	form_argsr   form_extra_fieldsinline_modelsscaffold_inline_form_models)rA   	converter
form_classs      rH   scaffold_formzModelView.scaffold_form  s     --dllDA	]]4::y.2.B.B(,(9(9+/+E+E.2nn151C1C040F0FH
 99*EJrI   c                     | j                  | j                  |       }t        j                  | j                  || j
                  | j                  |      }t        | j
                  ||      S )ah  
            Create form for the `index_view` using only the columns from
            `self.column_editable_list`.

            :param widget:
                WTForms widget class. Defaults to `XEditableWidget`.
            :param validators:
                `form_args` dict with only validators
                {'name': {'validators': [required()]}}
        )r   r   r   )r   r0   r   r   r8   r   column_editable_listr   )rA   widget
validatorsr   r   s        rH   scaffold_list_formzModelView.scaffold_list_form  sa     --dllDA	]]4::y.2.B.B(,(A(A.8:

 ))=)=z)/1 	1rI   c                 R   | j                  | j                  | | j                        }| j                  D ]p  }t	        |d      s|j                  | j                  ||      }-|j                  | j                  | | j                        }|j                  | j                  ||      }r |S )zu
            Contribute inline models to the form

            :param form_class:
                Form class
        inline_converter)inline_model_form_converterr0   r   r   rv   
contributer8   r   )rA   r   default_convertermcustom_converters        rH   r   z%ModelView.scaffold_inline_form_models  s     !<<LL$ 9 9; ## 		+A101.99JJ
A/
 11dD$=$= ?)44

J+J		+ rI   c                 &   | j                   sg S t               }| j                         D ]  }t        |d      s|j                  j
                  | j                  k(  r4t        | j                  dd      }t        |j                  j
                  dd      }||k7  rr|j                  j                  dv s|j                  |j                          g }| j                  D ]/  \  }}||v s|j                  t        | j                  |             1 |S )zh
            Return a list of joined tables by going through the
            displayed columns.
        rq   __bind_key__N)rr   
MANYTOMANY)r$   setrO   rv   rL   rT   r8   rW   rq   rB   addrX   _list_columnsrw   )rA   	relationsr   source_bindtarget_bindjoinedra   rB   s           rH   r?   zModelView.scaffold_auto_joins/  s    
 ..IE	))+ 	)Aq+&88??djj0 &djj.$G%ahhoo~tL+-;;##'BBMM!%%(	) ,, 	9JD$y gdjj$78	9 rI   c                 H    t        | j                  | j                  |||      S rh   )r!   r8   r0   )rA   rB   r   s      rH   _create_ajax_loaderzModelView._create_ajax_loaderQ  s    !$**dllD$PPrI   c                 L    | j                   j                  | j                        S )aL  
            Return a query for the model type.

            This method can be used to set a "persistent filter" on an index_view.

            Example::

                class MyView(ModelView):
                    def get_query(self):
                        return super(MyView, self).get_query().filter(User.username == current_user.username)


            If you override this method, don't forget to also override `get_count_query`, for displaying the correct
            item count in the list view, and `get_one`, which is used when retrieving records for the edit view.
        )r0   rY   r8   re   s    rH   	get_queryzModelView.get_queryU  s      ||!!$**--rI   c                     | j                   j                  t        j                  d            j	                  | j
                        S )a  
            Return a the count query for the model type

            A ``query(self.model).count()`` approach produces an excessive
            subquery, so ``query(func.count('*'))`` should be used instead.

            See commit ``#45a2723`` for details.
        *)r0   rY   r   countselect_fromr8   re   s    rH   get_count_queryzModelView.get_count_queryg  s0     ||!!$**S/2>>tzzJJrI   c                     |d| j                  |||d      \  }}}||nt        ||j                        }|r|j                  t	        |            }||fS |j                  |      }||fS )aj  
            Apply order_by to the query

            :param query:
                Query
            :pram joins:
                Current joins
            :param sort_joins:
                Sort joins (properties or tables)
            :param sort_field:
                Sort field
            :param sort_desc:
                Ascending or descending
        Fr\   )rb   rW   rX   order_byr   )rA   rY   rZ   
sort_joins
sort_field	sort_descr_   r   s           rH   	_order_byzModelView._order_byr  s|     !"&"8"8z^c"8"dE5%#(=ZgeZ^^6TFtF|4 e| v.e|rI   c              #      K   t         t        |          }|xs g D ]/  \  }}t        j                  | j
                  |      \  }}|||f 1 y wrh   )r6   r#   _get_default_orderr   r   r8   )rA   orderfieldrq   rj   rZ   rG   s         rH   r   zModelView._get_default_order  sU     i9;!&" 	)E933DJJFKD%y((	)s   AAc                    ||| j                   v r| j                   |   }| j                  j                  |      }t        |t              r0t        ||      D ]  \  }}| j                  |||||      \  }} ||fS | j                  |||||      \  }}||fS | j                         }	|	D ]  \  }}}| j                  |||||      \  }}  ||fS rh   )_sortable_columnsr4   rQ   rR   r   zipr   r   )
rA   rY   rZ   sort_columnr   r   r   
field_item	join_itemr   s
             rH   _apply_sortingzModelView._apply_sorting  s   "d444!33K@
!1155kB
j$/14Z1L f-
I'+~~eUIz[d'euf e| $(>>%
JXa#bLE5 e|	 ++-E5: _1
J	#~~eUJ
T]^u_ e|rI   c                    |j                  d      }|D ].  }|st        j                  |      }g }	g }
| j                  D ]  \  }}| j	                  |||d      \  }}}d}|| j	                  |||d      \  }}}||nt        ||j                        }|	j                  t        |t              j                  |             |
||nt        ||j                        }|
j                  t        |t              j                  |              |j                  t        |	       }||j                  t        |
       }1 ||||fS )z.
            Apply search to a query.
         Fr   N)r   r   parse_like_termr1   rb   rW   rX   rw   r   r   iliker   r   )rA   rY   count_queryrZ   count_joinssearchtermstermstmtfilter_stmtcount_filter_stmtr   r[   r_   count_aliasr   s                   rH   _apply_searchzModelView._apply_search  sp    S! 	JD((.DK "#22 Pt&*&<&<UE4\a&<&b#ue"*<@<R<RS^S^SW^c =S =e9Kk
 #(-WUEII5N""4#8#>#>t#DE$0&1&9Uw{TYT]T]?^F%,,T&'-B-H-H-NO!P$ LLk!23E&)006G1HI=	J@ k5+55rI   c                    |D ]  \  }}}| j                   |   }	d }
d }t        |	t        j                        rj|	j                  xs |	j
                  }| j                  j                  |g       }| j                  |||d      \  }}}
|| j                  |||d      \  }}}|	j                  |      }	 |	j                  |||
      }|	 |	j                  |||      } ||||fS # t        $ ro t        j                  |	j                        }t        |j                        dk(  r"t!        j"                  dt%        |	      z         n |	j                  ||      }Y w xY w# t        $ r |	j                  ||      }Y {w xY w)NFr      zLPlease update your custom filter %s to include additional `alias` parameter.)_filtersrR   r   r   r   r   r3   rQ   rb   cleanapply	TypeErrorinspect
getargspecrx   argsr{   r|   repr)rA   rY   r  rZ   r  r   idxflt_namevaluer   r_   r  
filter_keyr[   clean_valuespecs                   rH   _apply_filterszModelView._apply_filters  s   $+ )	F C5--$CEK #|::; \\7SZZ
))--j"=&*&<&<UE4\a&<&b#ue*<@<R<R###(	 =S =*9Kk ))E*K6		%e< &F"%))Kk"RKO)	FV k5+55#  	6))#))4tyy>Q&MM #JLPQTI#V W 		%5	6 ! F"%))K"EKFs%   3C%
E %A5EE E?>E?c                 x    || j                   }|r|j                  |      }|r|r|j                  ||z        }|S rh   )	page_sizelimitoffset)rA   rY   pager  s       rH   _apply_paginationzModelView._apply_pagination  s?    IKK	*EILL	!12ErI   c                 j   i }i }	| j                         }
| j                  s| j                         nd}t        |
d      r'|
j                  D ]  }|j
                  D ]  }d||<   	  | j                  r|r| j                  |
|||	|      \  }
}}}	|r&| j                  r| j                  |
|||	|      \  }
}}}	|r|j                         nd}| j                  D ]  }|
j                  t        |            }
 | j                  |
|||      \  }
}| j                  |
||      }
|r|
j!                         }
||
fS )a  
            Return records from the database.

            :param page:
                Page number
            :param sort_column:
                Sort column name
            :param sort_desc:
                Descending or ascending sort
            :param search:
                Search query
            :param execute:
                Execute query immediately? Default is `True`
            :param filters:
                List of filter tuples
            :param page_size:
                Number of results. Defaults to ModelView's page_size. Can be
                overriden to change the page_size limit. Removing the page_size
                limit requires setting page_size to 0 or False.
        N_join_entities)r   simple_list_pagerr   rv   r%  tables_search_supportedr  r  r  scalarr@   r   r   r   r#  all)rA   r"  r   r   r  r   executer  rZ   r  rY   r  entityr   r   js                   rH   get_listzModelView.get_list  sb   0  484J4Jd**,PT 5*+.. (#]] (E#'E%L((
 !!f595G5GHSHMHSHN	6P2E;{ t}}595H5HITINITIP	6R2E;{ )4""$ !! 	1AMM*Q-0E	1 **5%iPu &&udI> IIKEe|rI   c                     | j                   j                  | j                        j                  t	        j
                  |            S )aY  
            Return a single model by its id.

            Example::

                def get_one(self, id):
                    query = self.get_query()
                    return query.filter(self.model.id == id).one()

            Also see `get_query` for how to filter the list view.

            :param id:
                Model id
        )r0   rY   r8   rQ   r   
iterdecode)rA   ids     rH   get_onezModelView.get_oneP  s3     ||!!$**-11%2B2B22FGGrI   c                    t        |t              r_t        j                  j	                  dt        j                  j	                  d            r t        t        dt        |            d       yt        t        | +  |      S )NADMIN_RAISE_ON_INTEGRITY_ERRORADMIN_RAISE_ON_VIEW_EXCEPTIONzIntegrity error. %(message)s)messageerrorT)rR   r   r   configrQ   r   r   r   r6   r#   handle_view_exception)rA   excrG   s     rH   r9  zModelView.handle_view_exceptionb  sk    c>*!!%%0""&&'FG g<iPSnUW^_Y;C@@rI   c                     | j                   j                         }t        |      }| j                   j                  j	                  |g i        |S )z
            Build new instance of a model. Useful to override the Flask-Admin behavior
            when the model has a custom __init__ method.
        )r9   new_instancer   dispatchinit)rA   r8   states      rH   build_new_instancezModelView.build_new_instanceo  sC    
 **, u%##E2r2rI   c           	         	 | j                         } |j                  |       | j                  j                  |       | j	                  ||d       | j                  j                          | j                  ||d       |S # t        $ rj}| j                  |      s5t        t        dt        |            d       t        j                  d       | j                  j                          Y d}~yd}~ww xY w)ze
            Create model from form.

            :param form:
                Form instance
        Tz"Failed to create record. %(error)sr7  r7  zFailed to create record.NF)r@  populate_objr0   r   _on_model_changecommitafter_model_changer<   r9  r   r   strlog	exceptionrollbackrA   r   r8   exs       rH   create_modelzModelView.create_model~  s    	7++-EDe$LLU#!!$t4LL! ##D%6  	--b1gB#b'RT[\89LL!!#	s   A*B 	C4
A C//C4c           	         	  |j                   |       | j                  ||d       | j                  j                          | j	                  ||d       y# t
        $ rj}| j                  |      s5t        t        dt        |            d       t        j                  d       | j                  j                          Y d}~yd}~ww xY w)z
            Update model from form.

            :param form:
                Form instance
            :param model:
                Model instance
        Fz"Failed to update record. %(error)srB  r7  zFailed to update record.NT)rC  rD  r0   rE  rF  r<   r9  r   r   rG  rH  rI  rJ  rK  s       rH   update_modelzModelView.update_model  s    	8De$!!$u5LL! ##D%7  	--b1gB#b'RT[\89LL!!#	s   ?A 	CA CCc           	         	 | j                  |       | j                  j                          | j                  j                  |       | j                  j	                          | j                  |       y# t        $ rj}| j                  |      s5t        t        dt        |            d       t        j                  d       | j                  j                          Y d}~yd}~ww xY w)z^
            Delete model.

            :param model:
                Model to delete
        z"Failed to delete record. %(error)srB  r7  zFailed to delete record.NFT)on_model_deleter0   flushdeleterE  after_model_deleter<   r9  r   r   rG  rH  rI  rJ  )rA   r8   rL  s      rH   delete_modelzModelView.delete_model  s    	+  'LL LL&LL! ##E*  	--b1gB#b'RT[\89LL!!#	s   A A4 4	C'=A C""C'c                 N    |dk(  r| j                   syt        t        |   |      S )NrS  F)
can_deleter6   r#   is_action_allowed)rA   rB   rG   s     rH   rX  zModelView.is_action_allowed  s&    8DOOY7==rI   rS  Deletez1Are you sure you want to delete selected records?c           	         	 t        j                  | j                         | j                  |      }| j                  r|j                  d      }n.d}|j                         D ]  }| j                  |      s|dz  } | j                  j                          t        t        dd||      d       y # t        $ r<}| j                  |      s t        t        d	t        |      
      d       Y d }~y d }~ww xY w)NF)synchronize_sessionr   r   z Record was successfully deleted.z,%(count)s records were successfully deleted.)r   successz#Failed to delete records. %(error)srB  r7  )r   get_query_for_idsr   r8   fast_mass_deleterS  r*  rU  r0   rE  r   r   r<   r9  r   rG  )rA   idsrY   r   r   rL  s         rH   action_deletezModelView.action_delete  s    	Z++DNN,<djj#NE$$? #A((+
# LL!(=I !&( *34  	Z--b1'?s2wOQXYY		Zs   A4B2 7:B2 2	C7;2C22C7)NNNNNNNNrh   )T)NN)TN)@r=   
__module____qualname____doc__r   r$   r>   r(   r*   column_filtersr   AdminModelConverterr   InlineModelConverterr   r   FilterConverterr   r^  r   r    column_type_formattersr5   r	   form_optional_typesr   r7   rO   rb   r:   ro   r   r   r   r   r   r   r   r   r   r   r   r?   r   r   r   r   r   r   r  r  r#  r.  r2  r9  r@  rM  rO  rU  rX  r   r   r`  __classcell__)rG   s   @rH   r#   r#       s    "..J.C.2"4 "..E.C.2"4" $00N0L05$7  **B*>*.0< N(T  33 #'";"; 4|335 	 M;z 0L	 #* M SWLP:?zA$"N1C D6.`)!V18(6l\	$1(,DQ.$	K8)$&6P,6\
 *.FPH$A644> H"LMOZOZrI   r#   )6loggingr{   r  sqlalchemy.orm.attributesr   sqlalchemy.orm.baser   r   sqlalchemy.ormr   r   sqlalchemy.sql.expressionr   
sqlalchemyr	   r
   r   r   sqlalchemy.excr   r   r   flaskr   r   flask_admin._compatr   r   flask_admin.babelr   r   r   flask_admin.contrib.sqla.toolsr   flask_admin.modelr   flask_admin.model.formr   flask_admin.actionsr   flask_admin._backwardsr   flask_admin.contrib.sqlar   r   r   r   typefmtr    ajaxr!   	getLoggerrH  r#    rI   rH   <module>r     su       ; @ . * 0 0 ) *  $ 7 = = : + < & / I I ' $ g*+NZ NZrI   