    This provides default implementations for the methods that Flask-Login
    expects user objects to have.
    
        Checks the equality of two `UserMixin` objects using `get_id`.
        
        Checks the inequality of two `UserMixin` objects using `get_id`.
        
Checks the inequality of two `UserMixin` objects using `get_id`.

This provides default implementations for the methods that Flask-Login
expects user objects to have.

Flask-specific subclass of WTForms :class:`~wtforms.form.Form`.

    If ``formdata`` is not specified, this will use :attr:`flask.request.form`
    and :attr:`flask.request.files`.  Explicitly pass ``formdata=None`` to
    prevent this.
    
    This is the default Meta class which defines all the default values and
    therefore also the 'API' of the class Meta interface.
    
        wrap_formdata allows doing custom wrappers of WTForms formdata.

        The default implementation detects webob-style multidicts and wraps
        them, otherwise passes formdata back un-changed.

        :param form: The form.
        :param formdata: Form data.
        :return: A form-input wrapper compatible with WTForms.
        
        Override in subclasses to provide alternate translations factory.
        See the i18n documentation for more.

        :return: An object that provides gettext() and ngettext() methods.
        
        bind_field allows potential customization of how fields are bound.

        The default implementation simply passes the options to
        :meth:`UnboundField.bind`.

        :param unbound_field: The unbound field.
        :param options:
            A dictionary of options which are typically passed to the field.

        :return: A bound field
        
        render_field allows customization of how widget rendering is done.

        The default implementation calls ``field.widget(field, **render_kw)``
        
        Build a CSRF implementation. This is called once per form instance.

        The default implementation builds the class referenced to by
        :attr:`csrf_class` with zero arguments. If `csrf_class` is ``None``,
        will instead use the default implementation
        :class:`wtforms.csrf.session.SessionCSRF`.

        :return: A CSRF implementation.
        
        Given a dictionary of values, update values on this `Meta` instance.
        
        :param formdata:
            Used to pass data coming from the enduser, usually `request.POST` or
            equivalent. formdata should be some sort of request-data wrapper which
            can get multiple parameters from the form input, and values are unicode
            strings, e.g. a Werkzeug/Django/WebOb MultiDict
        :param obj:
            If `formdata` is empty or not provided, this object is checked for
            attributes matching form field names, which will be used for field
            values.
        :param prefix:
            If provided, all fields will have their name prefixed with the
            value.
        :param data:
            Accept a dictionary of data. This is only used if `formdata` and
            `obj` are not present.
        :param meta:
            If provided, this is a dictionary of values to override attributes
            on this form's meta instance.
        :param `**kwargs`:
            If `formdata` is empty or not provided and `obj` does not contain
            an attribute named the same as a field, form will assign the value
            of a matching keyword argument to the field, if one exists.
        
Consider the form submitted if there is an active request and
        the method is ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
        
Call :meth:`validate` only if the form is submitted.
        This is a shortcut for ``form.is_submitted() and form.validate()``.
        
Render the form's hidden fields in one call.

        A field is considered hidden if it uses the
        :class:`~wtforms.widgets.HiddenInput` widget.

        If ``fields`` are given, only render the given fields that
        are hidden.  If a string is passed, render the field with that
        name if it exists.

        .. versionchanged:: 0.13

           No longer wraps inputs in hidden div.
           This is valid HTML 5.

           Skip passed fields that aren't hidden.
           Skip passed names that don't exist.
        
Validate the form by calling ``validate`` on each field.
        Returns ``True`` if validation passes.

        If the form defines a ``validate_<fieldname>`` method, it is
        appended as an extra validator for the field's ``validate``.

        :param extra_validators: A dict mapping field names to lists of
            extra validator methods to run. Extra validators run after
            validators passed when creating the field. If the form has
            ``validate_<fieldname>``, it is the last extra validator.
        
wrap_formdata allows doing custom wrappers of WTForms formdata.

The default implementation detects webob-style multidicts and wraps
them, otherwise passes formdata back un-changed.

:param form: The form.
:param formdata: Form data.
:return: A form-input wrapper compatible with WTForms.

Override in subclasses to provide alternate translations factory.
See the i18n documentation for more.

:return: An object that provides gettext() and ngettext() methods.

bind_field allows potential customization of how fields are bound.

The default implementation simply passes the options to
:meth:`UnboundField.bind`.

:param unbound_field: The unbound field.
:param options:
    A dictionary of options which are typically passed to the field.

:return: A bound field

render_field allows customization of how widget rendering is done.

The default implementation calls ``field.widget(field, **render_kw)``

Build a CSRF implementation. This is called once per form instance.

The default implementation builds the class referenced to by
:attr:`csrf_class` with zero arguments. If `csrf_class` is ``None``,
will instead use the default implementation
:class:`wtforms.csrf.session.SessionCSRF`.

:return: A CSRF implementation.

Given a dictionary of values, update values on this `Meta` instance.

This is the default Meta class which defines all the default values and
therefore also the 'API' of the class Meta interface.

:param formdata:
    Used to pass data coming from the enduser, usually `request.POST` or
    equivalent. formdata should be some sort of request-data wrapper which
    can get multiple parameters from the form input, and values are unicode
    strings, e.g. a Werkzeug/Django/WebOb MultiDict
:param obj:
    If `formdata` is empty or not provided, this object is checked for
    attributes matching form field names, which will be used for field
    values.
:param prefix:
    If provided, all fields will have their name prefixed with the
    value.
:param data:
    Accept a dictionary of data. This is only used if `formdata` and
    `obj` are not present.
:param meta:
    If provided, this is a dictionary of values to override attributes
    on this form's meta instance.
:param `**kwargs`:
    If `formdata` is empty or not provided and `obj` does not contain
    an attribute named the same as a field, form will assign the value
    of a matching keyword argument to the field, if one exists.

the method is ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.

This is a shortcut for ``form.is_submitted() and form.validate()``.

A field is considered hidden if it uses the
:class:`~wtforms.widgets.HiddenInput` widget.

If ``fields`` are given, only render the given fields that
are hidden.  If a string is passed, render the field with that
name if it exists.

.. versionchanged:: 0.13

   No longer wraps inputs in hidden div.
   This is valid HTML 5.

   Skip passed fields that aren't hidden.
   Skip passed names that don't exist.

Returns ``True`` if validation passes.

If the form defines a ``validate_<fieldname>`` method, it is
appended as an extra validator for the field's ``validate``.

:param extra_validators: A dict mapping field names to lists of
    extra validator methods to run. Extra validators run after
    validators passed when creating the field. If the form has
    ``validate_<fieldname>``, it is the last extra validator.

If ``formdata`` is not specified, this will use :attr:`flask.request.form`
and :attr:`flask.request.files`.  Explicitly pass ``formdata=None`` to
prevent this.

    Special configurations for tests

    We use a dummy database and initialise it.
    
Special configurations for tests

We use a dummy database and initialise it.

    Test Admin Portal

    We use the cli-runner to run the admin-create command.
    Then we check if the admin portal is accessible to the newly created superuser.
    
Test Admin Portal

We use the cli-runner to run the admin-create command.
Then we check if the admin portal is accessible to the newly created superuser.

    Test for Database CLI Commands

    Test for initialisation, creation and admin user creation.
    
Test for Database CLI Commands

Test for initialisation, creation and admin user creation.

    Basic Version Test

    Check if endpoint is accessible
    
    Basic User Test

    Check if DB is accessible to the FastAPI App
    
Dictionary of Path, Expected Status Code and Data to Test for Visitors

    Test if Vistors get expected endpoints and status codes
    
    Test User Authentication Flow

    Tests Registeration, Email-Confirmation and Log-in along with appropriate redirects.
    
Test User Authentication Flow

Tests Registeration, Email-Confirmation and Log-in along with appropriate redirects.

    Our extended ModelView Class

    Refer to Flask-Admin Docs for more details

    https://flask-admin.readthedocs.io/en/latest/introduction/?highlight=ModelView#modelview-configuration-attributes
    
        Enable automatic detection of displayed foreign keys in this view
        and perform automatic joined loading for related models to improve
        query performance.

        Please note that detection is not recursive: if `__unicode__` method
        of related model uses another model to generate string representation, it
        will still make separate database call.
    
        List of parameters for SQLAlchemy `subqueryload`. Overrides `column_auto_select_related`
        property.

        For example::

            class PostAdmin(ModelView):
                column_select_related_list = ('user', 'city')

        You can also use properties::

                column_select_related_list = (Post.user, Post.city)

        Please refer to the `subqueryload` on list of possible values.
    
        Controls if list view should display all relations, not only many-to-one.
    
        Collection of the searchable columns.

        Example::

            class MyModelView(ModelView):
                column_searchable_list = ('name', 'email')

        You can also pass columns::

                column_searchable_list = (User.name, User.email)

        The following search rules apply:

        - If you enter ``ZZZ`` in the UI search field, it will generate ``ILIKE '%ZZZ%'``
          statement against searchable columns.

        - If you enter multiple words, each word will be searched separately, but
          only rows that contain all words will be displayed. For example, searching
          for ``abc def`` will find all rows that contain ``abc`` and ``def`` in one or
          more columns.

        - If you prefix your search term with ``^``, it will find all rows
          that start with ``^``. So, if you entered ``^ZZZ`` then ``ILIKE 'ZZZ%'`` will be used.

        - If you prefix your search term with ``=``, it will perform an exact match.
          For example, if you entered ``=ZZZ``, the statement ``ILIKE 'ZZZ'`` will be used.
    
        Collection of the column filters.

        Can contain either field names or instances of
        :class:`flask_admin.contrib.sqla.filters.BaseSQLAFilter` classes.

        Filters will be grouped by name when displayed in the drop-down.

            class MyModelView(BaseModelView):
                column_filters = ('user', 'email')

        or::

            from flask_admin.contrib.sqla.filters import BooleanEqualFilter

                column_filters = (BooleanEqualFilter(column=User.name, name='Name'),)

        or::

            from flask_admin.contrib.sqla.filters import BaseSQLAFilter

            class FilterLastNameBrown(BaseSQLAFilter):
                def apply(self, query, value, alias=None):
                    if value == '1':
                        return query.filter(self.column == "Brown")
                    else:
                        return query.filter(self.column != "Brown")

                def operation(self):
                    return 'is Brown'

                column_filters = [
                    FilterLastNameBrown(
                        User.last_name, 'Last Name', options=(('1', 'Yes'), ('0', 'No'))
                    )
                ]
    
        Model form conversion class. Use this to implement custom field conversion logic.

            class MyModelConverter(AdminModelConverter):
                pass

            class MyAdminView(ModelView):
                model_form_converter = MyModelConverter
    
        Inline model conversion class. If you need some kind of post-processing for inline
        forms, you can customize behavior by doing something like this::

            class MyInlineModelConverter(InlineModelConverter):
                def post_process(self, form_class, info):
                    form_class.value = wtf.StringField('value')
                    return form_class

                inline_model_form_converter = MyInlineModelConverter
    
        Field to filter converter.

        Override this attribute to use non-default converter.
    
        If set to `False` and user deletes more than one model using built in action,
        all models will be read from the database and then deleted one by one
        giving SQLAlchemy a chance to manually cleanup any dependencies (many-to-many
        relationships, etc).

        If set to `True`, will run a ``DELETE`` statement which is somewhat faster,
        but may leave corrupted data if you forget to configure ``DELETE
        CASCADE`` for your model.
    
        Inline related-model editing for models with parent-child relations.

        Accepts enumerable with one of the following possible values:

        1. Child model class::

                inline_models = (Post,)

        2. Child model class and additional options::

                inline_models = [(Post, dict(form_columns=['title']))]

        3. Django-like ``InlineFormAdmin`` class instance::

            from flask_admin.model.form import InlineFormAdmin

            class MyInlineModelForm(InlineFormAdmin):
                form_columns = ('title', 'date')

                inline_models = (MyInlineModelForm(MyInlineModel),)

        You can customize the generated field name by:

        1. Using the `form_name` property as a key to the options dictionary::

                inline_models = ((Post, dict(form_label='Hello')))

        2. Using forward relation name and `column_labels` property::

            class Model1(Base):
                pass

            class Model2(Base):
                # ...
                model1 = relation(Model1, backref='models')

            class MyModel1View(Base):
                inline_models = (Model2,)
                column_labels = {'models': 'Hello'}
    
        Map choices to form fields

        Example::

                form_choices = {'my_form_field': [
                    ('db_value', 'display_value'),
                ]}
    
        List of field types that should be optional if column is not nullable.

        Example::

                form_optional_types = (Boolean, Unicode)
    
       Ignore field that starts with "_"

       Example::

           class MyModelView(BaseModelView):
               ignore_hidden = False
    
            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
        
            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
        
            Return the primary key name(s) from a model
            If model has single primary key, will return a string and tuple otherwise
        
            Return the primary key value from a model object.
            If there are multiple primary keys, they're encoded into string representation.
        
            Return a dictionary of sortable columns.
            Key is column name, value is sort column/field.
        
            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.
        
            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.
        
            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.
        
            Return search placeholder.

            For example, if set column_labels and column_searchable_list:

                column_labels = dict(name='Name', last_name='Last Name')
                column_searchable_list = ('name', 'last_name')

            placeholder is: "Name, Last Name"
        
            Postprocess (add joins, etc) for a filter.

            :param filter:
                Filter object to postprocess
        
            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()]}}
        
            Contribute inline models to the form

            :param form_class:
                Form class
        
            Return a list of joined tables by going through the
            displayed columns.
        
            Model backend will override this to implement AJAX model loading.
        
            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.
        
            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.
        
            Apply order_by to the 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
        
            Return records from the database.

            :param page:
                Page number
            :param sort_column:
                Sort column name
                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.
        
            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
        
            Build new instance of a model. Useful to override the Flask-Admin behavior
            when the model has a custom __init__ method.
        
            Create model from form.

            :param form:
                Form instance
        
            Update model from form.

                Model instance
        
            Delete model.

                Model to delete
        
            Override this method to allow or disallow actions based
            on some condition.

            The default implementation only checks if the particular action
            is not in `action_disallowed_list`.
        
        Setting this to true will enable the details view. This is recommended
        when there are too many columns to display in the list_view.
    
Setting this to true will display the edit_view as a modal dialog.

Setting this to true will display the create_view as a modal dialog.

Setting this to true will display the details_view as a modal dialog.

        Collection of the model field names for the list view.
        If set to `None`, will get them from the model.

                column_list = ('name', 'last_name', 'email')

        (Added in 1.4.0) SQLAlchemy model attributes can be used instead of strings::

                column_list = ('name', User.last_name)

        When using SQLAlchemy models, you can reference related columns like this::
                column_list = ('<relationship>.<related column name>',)
    
        Collection of excluded list column names.

                column_exclude_list = ('last_name', 'email')
    
        Collection of the field names included in the details view.
    
        Collection of fields excluded from the details view.
    
        Collection of the field names included in the export.
    
        Dictionary of list view column formatters.

        For example, if you want to show price multiplied by
        two, you can do something like this::

                column_formatters = dict(price=lambda v, c, m, p: m.price*2)

        or using Jinja2 `macro` in template::

            from flask_admin.model.template import macro

                column_formatters = dict(price=macro('render_price'))

            # in template
            {% macro render_price(model, column) %}
                {{ model.price * 2 }}
            {% endmacro %}

        The Callback function has the prototype::

            def formatter(view, context, model, name):
                # `view` is current administrative view
                # `context` is instance of jinja2.runtime.Context
                # `model` is model instance
                # `name` is property name
                pass
    
        Dictionary of list view column formatters to be used for export.

        Defaults to column_formatters when set to None.

        Functions the same way as column_formatters except
        that macros are not supported.
    
        Dictionary of list view column formatters to be used for the detail view.

        Dictionary of value type formatters to be used in the export.

        By default, two types are formatted:

        1. ``None`` will be displayed as an empty string
        2. ``list`` will be joined using ', '

        Functions the same way as column_type_formatters.
    
        Dictionary of value type formatters to be used in the detail view.

        Dictionary where key is column name and value is string to display.

        Dictionary where key is column name and
        value is description for `list view` column or add/edit form field.

                column_descriptions = dict(
                    full_name='First and Last name'
                )
    
        Collection of the sortable columns for the list view.

                column_sortable_list = ('name', 'last_name')

        If you want to explicitly specify field/column to be used while
        sorting, you can use a tuple::

                column_sortable_list = ('name', ('user', 'user.username'))

        You can also specify multiple fields to be used while sorting::

                column_sortable_list = (
                    'name', ('user', ('user.first_name', 'user.last_name')))

        When using SQLAlchemy models, model attributes can be used instead
        of strings::

                column_sortable_list = ('name', ('user', User.username))
    
        Default sort column if no sorting is applied.

        Example::

                column_default_sort = 'user'

        You can use tuple to control ascending descending order. In following example, items
        will be sorted in descending order::

                column_default_sort = ('user', True)

        If you want to sort by more than one column,
        you can pass a list of tuples::

                column_default_sort = [('name', True), ('last_name', True)]
    
        Collection of the columns which can be edited from the list view.

                column_editable_list = ('name', 'last_name')
    
        Map choices to columns in list view

        Example::

                column_choices = {
                    'my_column': [
                        ('db_value', 'display_value'),
                    ]
                }
    
        Set to True to use human-readable names for filters in URL parameters.

        False by default so as to be robust across translations.

        Changing this parameter will break any existing URLs that have filters.
    
        Controls if the primary key should be displayed in the list view.
    
        Controls the display of the row actions (edit, delete, details, etc.)
        column in the list view.

        Useful for preventing a blank column from displaying if your view does
        not use any build-in or custom row actions.

        This column is not hidden automatically due to backwards compatibility.

        Note: This only affects display and does not control whether the row
        actions endpoints are accessible.
    
        List of row actions (instances of :class:`~flask_admin.model.template.BaseListRowAction`).

        Flask-Admin will generate standard per-row actions (edit, delete, etc)
        and will append custom actions from this list right after them.

            from flask_admin.model.template import EndpointLinkRowAction, LinkRowAction

                column_extra_row_actions = [
                    LinkRowAction('glyphicon glyphicon-off', 'http://direct.link/?id={row_id}'),
                    EndpointLinkRowAction('glyphicon glyphicon-test', 'my_view.index_view')
                ]
    
        Enable or disable simple list pager.
        If enabled, model interface would not run count query and will only show prev/next pager buttons.
    
        Form class. Override if you want to use custom form for your model.
        Will completely disable form scaffolding functionality.

            class MyForm(Form):
                name = StringField('Name')

                form = MyForm
    
        Base form class. Will be used by form scaffolding function when creating model form.

        Useful if you want to have custom constructor or override some fields.

        Example::

            class MyBaseForm(Form):
                def do_something(self):
                    pass

                form_base_class = MyBaseForm

        Dictionary of form field arguments. Refer to WTForms documentation for
        list of possible options.

        Example::

            from wtforms.validators import DataRequired
                form_args = dict(
                    name=dict(label='First Name', validators=[DataRequired()])
                )
    
        Collection of the model field names for the form. If set to `None` will
        get them from the model.

        Example::

                form_columns = ('name', 'email')

        (Added in 1.4.0) SQLAlchemy model attributes can be used instead of
        strings::

                form_columns = ('name', User.last_name)

        SQLA Note: Model attributes must be on the same model as your ModelView
        or you will need to use `inline_models`.
    
        Collection of excluded form field names.

                form_excluded_columns = ('last_name', 'email')
    
        Dictionary of form column overrides.

        Example::

                form_overrides = dict(name=wtf.FileField)
    
        Dictionary of form widget rendering arguments.
        Use this to customize how widget is rendered without using custom template.

        Example::

                form_widget_args = {
                    'description': {
                        'rows': 10,
                        'style': 'color: black'
                    },
                    'other_field': {
                        'disabled': True
                    }
                }

        Changing the format of a DateTimeField will require changes to both form_widget_args and form_args.

        Example::

            form_args = dict(
                start=dict(format='%Y-%m-%d %I:%M %p') # changes how the input is parsed by strptime (12 hour time)
            )
            form_widget_args = dict(
                start={
                    'data-date-format': u'yyyy-mm-dd HH:ii P',
                    'data-show-meridian': 'True'
                } # changes how the DateTimeField displays the time
            )
    
        Dictionary of additional fields.

        Example::

                form_extra_fields = {
                    'password': PasswordField('Password')
                }

        You can control order of form fields using ``form_columns`` property. For example::

                form_columns = ('name', 'email', 'password', 'secret')

                }

        In this case, password field will be put between email and secret fields that are autogenerated.
    
        Use AJAX for foreign key model loading.

        Should contain dictionary, where key is field name and value is either a dictionary which
        configures AJAX lookups or backend-specific `AjaxModelLoader` class instance.

        For example, it can look like::

                form_ajax_refs = {
                    'user': {
                        'fields': ('first_name', 'last_name', 'email'),
                        'placeholder': 'Please select',
                        'page_size': 10,
                        'minimum_input_length': 0,
                    }
                }

        Or with SQLAlchemy backend like this::

                    'user': QueryAjaxModelLoader('user', db.session, User, fields=['email'], page_size=10)
                }

        If you need custom loading functionality, you can implement your custom loading behavior
        in your `AjaxModelLoader` class.
    
        List of rendering rules for model creation form.

        This property changed default form rendering behavior and makes possible to rearrange order
        of rendered fields, add some text between fields, group them, etc. If not set, will use
        default Flask-Admin form rendering logic.

        Here's simple example which illustrates how to use::

            from flask_admin.form import rules

                form_rules = [
                    # Define field set with header text and four fields
                    rules.FieldSet(('first_name', 'last_name', 'email', 'phone'), 'User'),
                    # ... and it is just shortcut for:
                    rules.Header('User'),
                    rules.Field('first_name'),
                    rules.Field('last_name'),
                    # ...
                    # It is possible to create custom rule blocks:
                    MyBlock('Hello World'),
                    # It is possible to call macros from current context
                    rules.Macro('my_macro', foobar='baz')
                ]
    
        Customized rules for the edit form. Override `form_rules` if present.
    
        Customized rules for the create form. Override `form_rules` if present.
    
        Set of disallowed action names. For example, if you want to disable
        mass model deletion, do something like this:

                action_disallowed_list = ['delete']
    
        Maximum number of rows allowed for export.

        Unlimited by default. Uses `page_size` if set to `None`.
    
        A list of available export filetypes. `csv` only is default, but any
        filetypes supported by tablib can be used.

        Check tablib for https://github.com/kennethreitz/tablib/blob/master/README.rst
        for supported types.
    
            Generate Flask endpoint name. By default converts class name to lower case if endpoint is
            not explicitly provided.
        
            Return a human-readable column name.

            :param field:
                Model field name.
        
            Return list of row action objects, each is instance of
            :class:`~flask_admin.model.template.BaseListRowAction`
        
            Uses `get_column_names` to get a list of tuples with the model
            field name and formatted name for the columns in `column_list`
            and not in `column_exclude_list`. If `column_list` is not set,
            the columns from `scaffold_list_columns` will be used.
        
            field name and formatted name for the columns in `column_details_list`
            and not in `column_details_exclude_list`. If `column_details_list`
            is not set, the columns from `scaffold_list_columns` will be used.
        
            field name and formatted name for the columns in `column_export_list`
            and not in `column_export_exclude_list`. If `column_export_list` is
            not set, it will attempt to use the columns from `column_list`
            or finally the columns from `scaffold_list_columns` will be used.
        
            Verify that the provided filter object is valid.

            Override in model backend implementation to verify if
            the provided filter type is allowed.

                Filter object to verify.
        
            Return a list of filter objects.

            If your model backend implementation does not support filters,
            override this method and return `None`.
        
            Given a filter `flt`, return a unique name for that filter in
            this view.

            Does not include the `flt[n]_` portion of the filter name.

            :param index:
                Filter index in _filters array
            :param flt:
                Filter instance
        
            Returns non-lazy version of filter strings
        
            Get form class.

            If ``self.form`` is set, will return it and will call
            ``self.scaffold_form`` otherwise.

            Override to implement customized behavior.
        
            Get form class for the editable list view.

            Uses only validators from `form_args` to build the form class.

            Allows overriding the editable list view field/widget. For example::

                from flask_admin.model.widgets import XEditableWidget

                class CustomWidget(XEditableWidget):
                    def get_kwargs(self, subfield, kwargs):
                        if subfield.type == 'TextAreaField':
                            kwargs['data-type'] = 'textarea'
                            kwargs['data-rows'] = '20'
                        # elif: kwargs for other fields

                        return kwargs

                class MyModelView(BaseModelView):
                    def get_list_form(self):
                        return self.scaffold_list_form(widget=CustomWidget)
        
            Create form class for model creation view.

            Create form class for model editing view.

            Create form class for model delete view.

            Create form class for a model action.

            Instantiate model creation form and return it.

            Override to implement custom behavior.
        
            Instantiate model editing form and return it.

            Instantiate model delete form and return it.

            The delete form originally used a GET request, so delete_form
            accepts both GET and POST request for backwards compatibility.
        
            Instantiate model editing form for list view and return it.

            Instantiate model action form and return it.

            Validate the form on submit.

                Form to validate
        
            Return url where user is redirected after successful form save.

                Saved object
            :param is_created:
                Whether new object was created or existing one was updated

            For example, redirect use to object details view after form save::

                class MyModelView(ModelView):
                    can_view_details = True

                    def get_save_return_url(self, model, is_created):
                        return self.get_url('.details_view', id=model.id)

            Verify if column is sortable.

            Not case-sensitive.

                Column name.
        
            Verify if column is editable.

            Perform some actions before a model is created or updated.

            Called from create_model and update_model in the same transaction
            (if it has any meaning for a store backend).

            By default does nothing.

                Form used to create/update model
                Model that will be created/updated
                Will be set to True if model was created and to False if edited
        
            Perform some actions after a model was created or updated and
            committed to the database.

            Called from create_model after successful database commit.

                Model that was created/updated
                True if model was created, False if model was updated
        
            Perform some actions before a model is deleted.

            Called from delete_model in the same transaction

            By default do nothing.
        
            Perform some actions after a model was deleted and

            Called from delete_model after successful database commit

                Model that was deleted
        
            Perform additional actions to pre-fill the edit form.

            Called from edit_view, if the current action is rendering
            the form rather than receiving client side input, after
            default pre-filling has been performed.

            You only need to override this if you have added custom
            fields that depend on the database contents in a way that
            Flask-admin can't figure out by itself. Fields that were
            added by name of a normal column or relationship should
            work out of the box.

            :param id:
                id of the object that is going to be edited
        
            Prettify pythonic variable name.

            For example, 'hello_world' will be converted to 'Hello World'

                Name to prettify
        
        Returns message, which should be printed in case of failed validation.
        :param value: Invalid value
        :param filter: Filter
        :return: string
        
            Get active filters as dictionary of URL arguments and values

                List of filters from ViewArgs object
        
            Generate page URL with current page, sort column and
            other parameters.

            :param view:
                View name
            :param view_args:
                ViewArgs object with page number, filters, etc.
        
            Get unformatted field value from the model
        
            Returns the value to be displayed.

            :param context:
                :py:class:`jinja2.runtime.Context` if available
                Field name
            :param column_formatters:
                column_formatters to be used.
            :param column_type_formatters:
                column_type_formatters to be used.
        
            Returns the value to be displayed in the list view

                :py:class:`jinja2.runtime.Context`
                Field name
        
            Returns the value to be displayed in the detail view

                Field name
        
            Returns the value to be displayed in export.
            Allows export to use different (non HTML) formatters.

                Field name
        
            Process `form_ajax_refs` and generate model loaders that
            will be used by the `ajax_lookup` view.
        
            Delete model view. Only POST method is allowed.
        
            Exports a variety of formats using the tablib library.
        
            Edits a single column of a record in list view.
        
            Extra template arguments.

            If you need to pass some extra parameters to the template,
            you can override particular view function, contribute
            arguments you want to pass to the template and call parent view.

            These arguments are local for this request and will be discarded
            in the next request.

            Any value passed through ``_template_args`` will override whatever
            parent view function passed to the template.

            For example::

                class MyAdmin(ModelView):
                    @expose('/')
                    def index(self):
                        self._template_args['name'] = 'foobar'
                        self._template_args['code'] = '12345'
                        super(MyAdmin, self).index()
        
            Generate URL for the view. Override to change default behavior.
        
            Render template

            :param template:
                Template path to render
            :param kwargs:
                Template arguments
        
            Split words in PascalCase string into separate words.

                String to prettify
        
            Override this method if you want dynamically hide or show administrative views
            from Flask-Admin menu structure

            By default, item is visible in menu.

            Please note that item should be both visible and accessible to be displayed in menu.
        
            This method will be executed before calling any view method.

            It will execute the ``inaccessible_callback`` if the view is not
            accessible.

                View function name
                View function arguments
        
            This method will run actual view function.

            While it is similar to _handle_view, can be used to change
            arguments that are passed to the view.

            :param fn:
                View function
                Arguments
        
            Handle the response to inaccessible views.

            By default, it throw HTTP 403 error. Override this method to
            customize the behaviour.
        
            Generate URL for the endpoint. If you want to customize URL generation
            logic (persist some query string argument, for example), this is
            right place to do it.

                Flask endpoint name
                Arguments for `url_for`
        
            Initialize list of actions for the current administrative view.
        
            Return a list and a dictionary of allowed actions.
        
            Handle action request.

            :param return_view:
                Name of the view to return to after the request.
                If not provided, will return user to the return url in the form
                or the list view.
        
Enable automatic detection of displayed foreign keys in this view
and perform automatic joined loading for related models to improve
query performance.

Please note that detection is not recursive: if `__unicode__` method
of related model uses another model to generate string representation, it
will still make separate database call.

List of parameters for SQLAlchemy `subqueryload`. Overrides `column_auto_select_related`
property.

For example::

    class PostAdmin(ModelView):
        column_select_related_list = ('user', 'city')

You can also use properties::

        column_select_related_list = (Post.user, Post.city)

Please refer to the `subqueryload` on list of possible values.

Controls if list view should display all relations, not only many-to-one.

Collection of the searchable columns.

Example::

    class MyModelView(ModelView):
        column_searchable_list = ('name', 'email')

You can also pass columns::

        column_searchable_list = (User.name, User.email)

The following search rules apply:

- If you enter ``ZZZ`` in the UI search field, it will generate ``ILIKE '%ZZZ%'``
  statement against searchable columns.

- If you enter multiple words, each word will be searched separately, but
  only rows that contain all words will be displayed. For example, searching
  for ``abc def`` will find all rows that contain ``abc`` and ``def`` in one or
  more columns.

- If you prefix your search term with ``^``, it will find all rows
  that start with ``^``. So, if you entered ``^ZZZ`` then ``ILIKE 'ZZZ%'`` will be used.

- If you prefix your search term with ``=``, it will perform an exact match.
  For example, if you entered ``=ZZZ``, the statement ``ILIKE 'ZZZ'`` will be used.

Collection of the column filters.

Can contain either field names or instances of
:class:`flask_admin.contrib.sqla.filters.BaseSQLAFilter` classes.

Filters will be grouped by name when displayed in the drop-down.

    class MyModelView(BaseModelView):
        column_filters = ('user', 'email')

or::

    from flask_admin.contrib.sqla.filters import BooleanEqualFilter

        column_filters = (BooleanEqualFilter(column=User.name, name='Name'),)

or::

    from flask_admin.contrib.sqla.filters import BaseSQLAFilter

    class FilterLastNameBrown(BaseSQLAFilter):
        def apply(self, query, value, alias=None):
            if value == '1':
                return query.filter(self.column == "Brown")
            else:
                return query.filter(self.column != "Brown")

        def operation(self):
            return 'is Brown'

        column_filters = [
            FilterLastNameBrown(
                User.last_name, 'Last Name', options=(('1', 'Yes'), ('0', 'No'))
            )
        ]

Model form conversion class. Use this to implement custom field conversion logic.

    class MyModelConverter(AdminModelConverter):
        pass

    class MyAdminView(ModelView):
        model_form_converter = MyModelConverter

Inline model conversion class. If you need some kind of post-processing for inline
forms, you can customize behavior by doing something like this::

    class MyInlineModelConverter(InlineModelConverter):
        def post_process(self, form_class, info):
            form_class.value = wtf.StringField('value')
            return form_class

        inline_model_form_converter = MyInlineModelConverter

Field to filter converter.

Override this attribute to use non-default converter.

If set to `False` and user deletes more than one model using built in action,
all models will be read from the database and then deleted one by one
giving SQLAlchemy a chance to manually cleanup any dependencies (many-to-many
relationships, etc).

If set to `True`, will run a ``DELETE`` statement which is somewhat faster,
but may leave corrupted data if you forget to configure ``DELETE
CASCADE`` for your model.

Inline related-model editing for models with parent-child relations.

Accepts enumerable with one of the following possible values:

1. Child model class::

        inline_models = (Post,)

2. Child model class and additional options::

        inline_models = [(Post, dict(form_columns=['title']))]

3. Django-like ``InlineFormAdmin`` class instance::

    from flask_admin.model.form import InlineFormAdmin

    class MyInlineModelForm(InlineFormAdmin):
        form_columns = ('title', 'date')

        inline_models = (MyInlineModelForm(MyInlineModel),)

You can customize the generated field name by:

1. Using the `form_name` property as a key to the options dictionary::

        inline_models = ((Post, dict(form_label='Hello')))

2. Using forward relation name and `column_labels` property::

    class Model1(Base):
        pass

    class Model2(Base):
        # ...
        model1 = relation(Model1, backref='models')

    class MyModel1View(Base):
        inline_models = (Model2,)
        column_labels = {'models': 'Hello'}

Map choices to form fields

Example::

        form_choices = {'my_form_field': [
            ('db_value', 'display_value'),
        ]}

List of field types that should be optional if column is not nullable.

Example::

        form_optional_types = (Boolean, Unicode)

Ignore field that starts with "_"

Example::

        ignore_hidden = False

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

self, model, session, name=None, category=None, endpoint=None, url=None, static_folder=None, menu_class_name=None, menu_icon_type=None, menu_icon_value=None

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

Return the primary key name(s) from a model
If model has single primary key, will return a string and tuple otherwise

Return the primary key value from a model object.
If there are multiple primary keys, they're encoded into string representation.

Return a dictionary of sortable columns.
Key is column name, value is sort column/field.

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.

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.

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.

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"

Postprocess (add joins, etc) for a filter.

:param filter:
    Filter object to postprocess

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()]}}

Contribute inline models to the form

:param form_class:
    Form class

Return a list of joined tables by going through the
displayed columns.

Model backend will override this to implement AJAX model loading.

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.

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.

Apply order_by to the 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

Return records from the database.

:param page:
    Page number
:param sort_column:
    Sort column name
    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.

self, page, sort_column, sort_desc, search, filters, execute=True, page_size=None

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

Build new instance of a model. Useful to override the Flask-Admin behavior
when the model has a custom __init__ method.

Update model from form.

:param form:
    Form instance
    Model instance

Override this method to allow or disallow actions based
on some condition.

The default implementation only checks if the particular action
is not in `action_disallowed_list`.

Setting this to true will enable the details view. This is recommended
when there are too many columns to display in the list_view.

Collection of the model field names for the list view.
If set to `None`, will get them from the model.

        column_list = ('name', 'last_name', 'email')

(Added in 1.4.0) SQLAlchemy model attributes can be used instead of strings::

        column_list = ('name', User.last_name)

When using SQLAlchemy models, you can reference related columns like this::
        column_list = ('<relationship>.<related column name>',)

Collection of excluded list column names.

        column_exclude_list = ('last_name', 'email')

Collection of the field names included in the details view.

Collection of the field names included in the export.

Dictionary of list view column formatters.

For example, if you want to show price multiplied by
two, you can do something like this::

        column_formatters = dict(price=lambda v, c, m, p: m.price*2)

or using Jinja2 `macro` in template::

    from flask_admin.model.template import macro

        column_formatters = dict(price=macro('render_price'))

    # in template
    {% macro render_price(model, column) %}
        {{ model.price * 2 }}
    {% endmacro %}

The Callback function has the prototype::

    def formatter(view, context, model, name):
        # `view` is current administrative view
        # `context` is instance of jinja2.runtime.Context
        # `model` is model instance
        # `name` is property name
        pass

Dictionary of list view column formatters to be used for export.

Defaults to column_formatters when set to None.

Functions the same way as column_formatters except
that macros are not supported.

Dictionary of list view column formatters to be used for the detail view.

Dictionary of value type formatters to be used in the export.

By default, two types are formatted:

1. ``None`` will be displayed as an empty string
2. ``list`` will be joined using ', '

Functions the same way as column_type_formatters.

Dictionary of value type formatters to be used in the detail view.

Dictionary where key is column name and value is string to display.

        column_labels = dict(name='Name', last_name='Last Name')

Dictionary where key is column name and
value is description for `list view` column or add/edit form field.

        column_descriptions = dict(
            full_name='First and Last name'
        )

Collection of the sortable columns for the list view.

        column_sortable_list = ('name', 'last_name')

If you want to explicitly specify field/column to be used while
sorting, you can use a tuple::

        column_sortable_list = ('name', ('user', 'user.username'))

You can also specify multiple fields to be used while sorting::

        column_sortable_list = (
            'name', ('user', ('user.first_name', 'user.last_name')))

When using SQLAlchemy models, model attributes can be used instead
of strings::

        column_sortable_list = ('name', ('user', User.username))

Default sort column if no sorting is applied.

Example::

        column_default_sort = 'user'

You can use tuple to control ascending descending order. In following example, items
will be sorted in descending order::

        column_default_sort = ('user', True)

If you want to sort by more than one column,
you can pass a list of tuples::

        column_default_sort = [('name', True), ('last_name', True)]

Collection of the columns which can be edited from the list view.

        column_editable_list = ('name', 'last_name')

Map choices to columns in list view

Example::

        column_choices = {
            'my_column': [
                ('db_value', 'display_value'),
            ]
        }

Set to True to use human-readable names for filters in URL parameters.

False by default so as to be robust across translations.

Changing this parameter will break any existing URLs that have filters.

Controls if the primary key should be displayed in the list view.

Controls the display of the row actions (edit, delete, details, etc.)
column in the list view.

Useful for preventing a blank column from displaying if your view does
not use any build-in or custom row actions.

This column is not hidden automatically due to backwards compatibility.

Note: This only affects display and does not control whether the row
actions endpoints are accessible.

List of row actions (instances of :class:`~flask_admin.model.template.BaseListRowAction`).

Flask-Admin will generate standard per-row actions (edit, delete, etc)
and will append custom actions from this list right after them.

    from flask_admin.model.template import EndpointLinkRowAction, LinkRowAction

        column_extra_row_actions = [
            LinkRowAction('glyphicon glyphicon-off', 'http://direct.link/?id={row_id}'),
            EndpointLinkRowAction('glyphicon glyphicon-test', 'my_view.index_view')
        ]

Enable or disable simple list pager.
If enabled, model interface would not run count query and will only show prev/next pager buttons.

Form class. Override if you want to use custom form for your model.
Will completely disable form scaffolding functionality.

    class MyForm(Form):
        name = StringField('Name')

        form = MyForm

Base form class. Will be used by form scaffolding function when creating model form.

Useful if you want to have custom constructor or override some fields.

Example::

    class MyBaseForm(Form):
        def do_something(self):
            pass

        form_base_class = MyBaseForm

Dictionary of form field arguments. Refer to WTForms documentation for
list of possible options.

Example::

    from wtforms.validators import DataRequired
        form_args = dict(
            name=dict(label='First Name', validators=[DataRequired()])
        )

Collection of the model field names for the form. If set to `None` will
get them from the model.

Example::

        form_columns = ('name', 'email')

(Added in 1.4.0) SQLAlchemy model attributes can be used instead of
strings::

        form_columns = ('name', User.last_name)

SQLA Note: Model attributes must be on the same model as your ModelView
or you will need to use `inline_models`.

Collection of excluded form field names.

        form_excluded_columns = ('last_name', 'email')

Dictionary of form column overrides.

Example::

        form_overrides = dict(name=wtf.FileField)

Dictionary of form widget rendering arguments.
Use this to customize how widget is rendered without using custom template.

Example::

        form_widget_args = {
            'description': {
                'rows': 10,
                'style': 'color: black'
            },
            'other_field': {
                'disabled': True
            }
        }

Changing the format of a DateTimeField will require changes to both form_widget_args and form_args.

Example::

    form_args = dict(
        start=dict(format='%Y-%m-%d %I:%M %p') # changes how the input is parsed by strptime (12 hour time)
    )
    form_widget_args = dict(
        start={
            'data-date-format': u'yyyy-mm-dd HH:ii P',
            'data-show-meridian': 'True'
        } # changes how the DateTimeField displays the time
    )

Dictionary of additional fields.

Example::

        form_extra_fields = {
            'password': PasswordField('Password')
        }

You can control order of form fields using ``form_columns`` property. For example::

        form_columns = ('name', 'email', 'password', 'secret')

        }

In this case, password field will be put between email and secret fields that are autogenerated.

Use AJAX for foreign key model loading.

Should contain dictionary, where key is field name and value is either a dictionary which
configures AJAX lookups or backend-specific `AjaxModelLoader` class instance.

For example, it can look like::

        form_ajax_refs = {
            'user': {
                'fields': ('first_name', 'last_name', 'email'),
                'placeholder': 'Please select',
                'page_size': 10,
                'minimum_input_length': 0,
            }
        }

Or with SQLAlchemy backend like this::

            'user': QueryAjaxModelLoader('user', db.session, User, fields=['email'], page_size=10)
        }

If you need custom loading functionality, you can implement your custom loading behavior
in your `AjaxModelLoader` class.

List of rendering rules for model creation form.

This property changed default form rendering behavior and makes possible to rearrange order
of rendered fields, add some text between fields, group them, etc. If not set, will use
default Flask-Admin form rendering logic.

Here's simple example which illustrates how to use::

    from flask_admin.form import rules

        form_rules = [
            # Define field set with header text and four fields
            rules.FieldSet(('first_name', 'last_name', 'email', 'phone'), 'User'),
            # ... and it is just shortcut for:
            rules.Header('User'),
            rules.Field('first_name'),
            rules.Field('last_name'),
            # ...
            # It is possible to create custom rule blocks:
            MyBlock('Hello World'),
            # It is possible to call macros from current context
            rules.Macro('my_macro', foobar='baz')
        ]

Customized rules for the edit form. Override `form_rules` if present.

Customized rules for the create form. Override `form_rules` if present.

Set of disallowed action names. For example, if you want to disable
mass model deletion, do something like this:

        action_disallowed_list = ['delete']

Maximum number of rows allowed for export.

Unlimited by default. Uses `page_size` if set to `None`.

A list of available export filetypes. `csv` only is default, but any
filetypes supported by tablib can be used.

Check tablib for https://github.com/kennethreitz/tablib/blob/master/README.rst
for supported types.

Generate Flask endpoint name. By default converts class name to lower case if endpoint is
not explicitly provided.

Return a human-readable column name.

:param field:
    Model field name.

Return list of row action objects, each is instance of
:class:`~flask_admin.model.template.BaseListRowAction`

Uses `get_column_names` to get a list of tuples with the model
field name and formatted name for the columns in `column_list`
and not in `column_exclude_list`. If `column_list` is not set,
the columns from `scaffold_list_columns` will be used.

field name and formatted name for the columns in `column_details_list`
and not in `column_details_exclude_list`. If `column_details_list`
is not set, the columns from `scaffold_list_columns` will be used.

field name and formatted name for the columns in `column_export_list`
and not in `column_export_exclude_list`. If `column_export_list` is
not set, it will attempt to use the columns from `column_list`
or finally the columns from `scaffold_list_columns` will be used.

Verify that the provided filter object is valid.

Override in model backend implementation to verify if
the provided filter type is allowed.

    Filter object to verify.

Return a list of filter objects.

If your model backend implementation does not support filters,
override this method and return `None`.

Given a filter `flt`, return a unique name for that filter in
this view.

Does not include the `flt[n]_` portion of the filter name.

:param index:
    Filter index in _filters array
:param flt:
    Filter instance

Get form class.

If ``self.form`` is set, will return it and will call
``self.scaffold_form`` otherwise.

Override to implement customized behavior.

Get form class for the editable list view.

Uses only validators from `form_args` to build the form class.

Allows overriding the editable list view field/widget. For example::

    from flask_admin.model.widgets import XEditableWidget

    class CustomWidget(XEditableWidget):
        def get_kwargs(self, subfield, kwargs):
            if subfield.type == 'TextAreaField':
                kwargs['data-type'] = 'textarea'
                kwargs['data-rows'] = '20'
            # elif: kwargs for other fields

            return kwargs

        def get_list_form(self):
            return self.scaffold_list_form(widget=CustomWidget)

Create form class for model creation view.

Create form class for model editing view.

Create form class for model delete view.

Create form class for a model action.

Instantiate model creation form and return it.

Override to implement custom behavior.

Instantiate model editing form and return it.

Instantiate model delete form and return it.

The delete form originally used a GET request, so delete_form
accepts both GET and POST request for backwards compatibility.

Instantiate model editing form for list view and return it.

Instantiate model action form and return it.

Validate the form on submit.

    Form to validate

Return url where user is redirected after successful form save.

    Saved object
:param is_created:
    Whether new object was created or existing one was updated

For example, redirect use to object details view after form save::

        can_view_details = True

        def get_save_return_url(self, model, is_created):
            return self.get_url('.details_view', id=model.id)

Verify if column is sortable.

Not case-sensitive.

    Column name.

Perform some actions before a model is created or updated.

Called from create_model and update_model in the same transaction
(if it has any meaning for a store backend).

By default does nothing.

    Form used to create/update model
    Model that will be created/updated
    Will be set to True if model was created and to False if edited

Perform some actions after a model was created or updated and
committed to the database.

Called from create_model after successful database commit.

    Model that was created/updated
    True if model was created, False if model was updated

Perform some actions before a model is deleted.

Called from delete_model in the same transaction

By default do nothing.

Perform some actions after a model was deleted and

Called from delete_model after successful database commit

    Model that was deleted

Perform additional actions to pre-fill the edit form.

Called from edit_view, if the current action is rendering
the form rather than receiving client side input, after
default pre-filling has been performed.

You only need to override this if you have added custom
fields that depend on the database contents in a way that
Flask-admin can't figure out by itself. Fields that were
added by name of a normal column or relationship should
work out of the box.

:param id:
    id of the object that is going to be edited

Prettify pythonic variable name.

For example, 'hello_world' will be converted to 'Hello World'

    Name to prettify

Returns message, which should be printed in case of failed validation.
:param value: Invalid value
:param filter: Filter
:return: string

Get active filters as dictionary of URL arguments and values

    List of filters from ViewArgs object

Generate page URL with current page, sort column and
other parameters.

:param view:
    View name
:param view_args:
    ViewArgs object with page number, filters, etc.

Returns the value to be displayed.

:param context:
    :py:class:`jinja2.runtime.Context` if available
    Field name
:param column_formatters:
    column_formatters to be used.
:param column_type_formatters:
    column_type_formatters to be used.

self, context, model, name, column_formatters, column_type_formatters

Returns the value to be displayed in the list view

    :py:class:`jinja2.runtime.Context`
    Field name

Returns the value to be displayed in the detail view

    Field name

Returns the value to be displayed in export.
Allows export to use different (non HTML) formatters.

    Field name

Process `form_ajax_refs` and generate model loaders that
will be used by the `ajax_lookup` view.

Extra template arguments.

If you need to pass some extra parameters to the template,
you can override particular view function, contribute
arguments you want to pass to the template and call parent view.

These arguments are local for this request and will be discarded
in the next request.

Any value passed through ``_template_args`` will override whatever
parent view function passed to the template.

    class MyAdmin(ModelView):
        @expose('/')
        def index(self):
            self._template_args['name'] = 'foobar'
            self._template_args['code'] = '12345'
            super(MyAdmin, self).index()

Generate URL for the view. Override to change default behavior.

Render template

:param template:
    Template path to render
:param kwargs:
    Template arguments

Split words in PascalCase string into separate words.

    String to prettify

Override this method if you want dynamically hide or show administrative views
from Flask-Admin menu structure

By default, item is visible in menu.

Please note that item should be both visible and accessible to be displayed in menu.

This method will be executed before calling any view method.

It will execute the ``inaccessible_callback`` if the view is not
accessible.

    View function name
    View function arguments

This method will run actual view function.

While it is similar to _handle_view, can be used to change
arguments that are passed to the view.

:param fn:
    View function
    Arguments

Handle the response to inaccessible views.

By default, it throw HTTP 403 error. Override this method to
customize the behaviour.

Generate URL for the endpoint. If you want to customize URL generation
logic (persist some query string argument, for example), this is
right place to do it.

    Flask endpoint name
    Arguments for `url_for`

Initialize list of actions for the current administrative view.

Handle action request.

:param return_view:
    Name of the view to return to after the request.
    If not provided, will return user to the return url in the form
    or the list view.

Our extended ModelView Class

Refer to Flask-Admin Docs for more details

https://flask-admin.readthedocs.io/en/latest/introduction/?highlight=ModelView#modelview-configuration-attributes

This file describes the errors and the message the user should see.

    Used to simulate a error 500 for test coverage of 500 handling
    
    Thrown when a user accesses a page with @flask_login.login_required
    
Thrown when a user accesses a page with @flask_login.login_required

This is the main views module.

You should import all other views into this file rather than individually importing in __init__.py

    A simple contact us form with basic validation.

    This dummy form has not been linked to any database.
    
A simple contact us form with basic validation.

This dummy form has not been linked to any database.