geonature.core.gn_permissions.admin

Classes

RoleFilter

Base SQLAlchemy filter.

ModuleFilter

Base SQLAlchemy filter.

ObjectFilter

Base SQLAlchemy filter.

ActionFilter

Base SQLAlchemy filter.

ScopeFilter

Base SQLAlchemy filter.

OptionSelect2Widget

Select2 styled select widget.

OptionQuerySelectField

Overrides the QuerySelectField class from flask admin to allow

UserAjaxModelLoader

Ajax related model loader. Override this to implement custom loading behavior.

AreaAjaxModelLoader

Ajax related model loader. Override this to implement custom loading behavior.

TaxrefAjaxModelLoader

Ajax related model loader. Override this to implement custom loading behavior.

ObjectAdmin

SQLAlchemy model view

PermissionAdmin

SQLAlchemy model view

PermissionAvailableAdmin

SQLAlchemy model view

RolePermAdmin

SQLAlchemy model view

GroupPermAdmin

SQLAlchemy model view

UserPermAdmin

SQLAlchemy model view

Functions

filters_formatter(v, c, m, p)

modules_formatter(view, context, model, name)

groups_formatter(view, context, model, name)

role_formatter(view, context, model, name)

list_permissions_formatter(permissions, ...)

Render a list of permissions for module-object-action item as an HTML table.

permissions_formatter(view, context, model, name)

permissions_count_formatter(view, context, model, name)

Module Contents

class geonature.core.gn_permissions.admin.RoleFilter(column: flask_admin._types.T_COLUMN, name: str, options: flask_admin._types.T_OPTIONS = None, data_type: flask_admin._types.T_WIDGET_TYPE = None)[source]

Bases: geonature.core.admin.utils.DynamicOptionsMixin, flask_admin.contrib.sqla.filters.FilterEqual

Base SQLAlchemy filter.

The column argument accepts either a SQLAlchemy column / InstrumentedAttribute or a dotted-path string that walks relationships on the view’s model. String paths are resolved when the filter is attached to a view, and any joins required to reach the target column are added automatically.

Note

A filter constructed with a dotted-path string caches its resolved attribute and join path against the first model it sees. Re-using the same filter instance across views with different models raises RuntimeError – construct a new filter instance per view in that case. Filters constructed with a real column / InstrumentedAttribute are freely shareable.

Example:

class PostAdmin(ModelView):
    column_filters = [
        # Pass a column object directly:
        FilterEqual(column=Post.title, name="Title"),
        # Or use a dotted path resolved against the view's model:
        FilterLike(column="author.account.email", name="Author Email"),
    ]
get_dynamic_options(view)[source]
class geonature.core.gn_permissions.admin.ModuleFilter(column: flask_admin._types.T_COLUMN, name: str, options: flask_admin._types.T_OPTIONS = None, data_type: flask_admin._types.T_WIDGET_TYPE = None)[source]

Bases: geonature.core.admin.utils.DynamicOptionsMixin, flask_admin.contrib.sqla.filters.FilterEqual

Base SQLAlchemy filter.

The column argument accepts either a SQLAlchemy column / InstrumentedAttribute or a dotted-path string that walks relationships on the view’s model. String paths are resolved when the filter is attached to a view, and any joins required to reach the target column are added automatically.

Note

A filter constructed with a dotted-path string caches its resolved attribute and join path against the first model it sees. Re-using the same filter instance across views with different models raises RuntimeError – construct a new filter instance per view in that case. Filters constructed with a real column / InstrumentedAttribute are freely shareable.

Example:

class PostAdmin(ModelView):
    column_filters = [
        # Pass a column object directly:
        FilterEqual(column=Post.title, name="Title"),
        # Or use a dotted path resolved against the view's model:
        FilterLike(column="author.account.email", name="Author Email"),
    ]
get_dynamic_options(view)[source]
class geonature.core.gn_permissions.admin.ObjectFilter(column: flask_admin._types.T_COLUMN, name: str, options: flask_admin._types.T_OPTIONS = None, data_type: flask_admin._types.T_WIDGET_TYPE = None)[source]

Bases: geonature.core.admin.utils.DynamicOptionsMixin, flask_admin.contrib.sqla.filters.FilterEqual

Base SQLAlchemy filter.

The column argument accepts either a SQLAlchemy column / InstrumentedAttribute or a dotted-path string that walks relationships on the view’s model. String paths are resolved when the filter is attached to a view, and any joins required to reach the target column are added automatically.

Note

A filter constructed with a dotted-path string caches its resolved attribute and join path against the first model it sees. Re-using the same filter instance across views with different models raises RuntimeError – construct a new filter instance per view in that case. Filters constructed with a real column / InstrumentedAttribute are freely shareable.

Example:

class PostAdmin(ModelView):
    column_filters = [
        # Pass a column object directly:
        FilterEqual(column=Post.title, name="Title"),
        # Or use a dotted path resolved against the view's model:
        FilterLike(column="author.account.email", name="Author Email"),
    ]
get_dynamic_options(view)[source]
class geonature.core.gn_permissions.admin.ActionFilter(column: flask_admin._types.T_COLUMN, name: str, options: flask_admin._types.T_OPTIONS = None, data_type: flask_admin._types.T_WIDGET_TYPE = None)[source]

Bases: geonature.core.admin.utils.DynamicOptionsMixin, flask_admin.contrib.sqla.filters.FilterEqual

Base SQLAlchemy filter.

The column argument accepts either a SQLAlchemy column / InstrumentedAttribute or a dotted-path string that walks relationships on the view’s model. String paths are resolved when the filter is attached to a view, and any joins required to reach the target column are added automatically.

Note

A filter constructed with a dotted-path string caches its resolved attribute and join path against the first model it sees. Re-using the same filter instance across views with different models raises RuntimeError – construct a new filter instance per view in that case. Filters constructed with a real column / InstrumentedAttribute are freely shareable.

Example:

class PostAdmin(ModelView):
    column_filters = [
        # Pass a column object directly:
        FilterEqual(column=Post.title, name="Title"),
        # Or use a dotted path resolved against the view's model:
        FilterLike(column="author.account.email", name="Author Email"),
    ]
get_dynamic_options(view)[source]
class geonature.core.gn_permissions.admin.ScopeFilter(column: flask_admin._types.T_COLUMN, name: str, options: flask_admin._types.T_OPTIONS = None, data_type: flask_admin._types.T_WIDGET_TYPE = None)[source]

Bases: geonature.core.admin.utils.DynamicOptionsMixin, flask_admin.contrib.sqla.filters.FilterEqual

Base SQLAlchemy filter.

The column argument accepts either a SQLAlchemy column / InstrumentedAttribute or a dotted-path string that walks relationships on the view’s model. String paths are resolved when the filter is attached to a view, and any joins required to reach the target column are added automatically.

Note

A filter constructed with a dotted-path string caches its resolved attribute and join path against the first model it sees. Re-using the same filter instance across views with different models raises RuntimeError – construct a new filter instance per view in that case. Filters constructed with a real column / InstrumentedAttribute are freely shareable.

Example:

class PostAdmin(ModelView):
    column_filters = [
        # Pass a column object directly:
        FilterEqual(column=Post.title, name="Title"),
        # Or use a dotted path resolved against the view's model:
        FilterLike(column="author.account.email", name="Author Email"),
    ]
apply(query, value, alias=None)[source]

Apply search criteria to the query and return new query.

Paramètres:
  • query – Query

  • value – Search criteria

get_dynamic_options(view)[source]
geonature.core.gn_permissions.admin.filters_formatter(v, c, m, p)[source]
geonature.core.gn_permissions.admin.modules_formatter(view, context, model, name)[source]
geonature.core.gn_permissions.admin.groups_formatter(view, context, model, name)[source]
geonature.core.gn_permissions.admin.role_formatter(view, context, model, name)[source]
geonature.core.gn_permissions.admin.list_permissions_formatter(permissions, available_permission, managable, current_user, return_url)[source]

Render a list of permissions for module-object-action item as an HTML table.

This function generates an HTML table that displays permissions associated to specific

module, object, or action. Each permission is rendered with its status, expiration

date, and associated filters. If the permissions are manageable, edit and delete options are included for each permission.

Parameters

permissionslist[Permission]

A list of permission objects to be rendered.

available_permissionPermissionAvailable

the permission template.

managablebool

A boolean indicating whether the permissions are manageable. If True, edit and delete options will be included in the rendered HTML.

modelUser

current user

return_urlstr

The URL to return to after performing an action (e.g., editing or deleting a permission).

Returns

str

An HTML string representing the permissions table.

Notes

The function uses Bootstrap classes for styling the table and its elements. If a permission has filters, they are displayed as a list within the table cell. If a permission is not active, it is marked with a “table-secondary” class and a “text-danger” class for the expiration date. If a permission is active but has an expiration date, it is marked with a “text-success” class for the expiration date.

geonature.core.gn_permissions.admin.permissions_formatter(view, context, model, name)[source]
geonature.core.gn_permissions.admin.permissions_count_formatter(view, context, model, name)[source]
class geonature.core.gn_permissions.admin.OptionSelect2Widget(multiple=False)[source]

Bases: flask_admin.form.widgets.Select2Widget

Select2 styled select widget.

You must include select2.js, form-x.x.x.js and select2 stylesheet for it to work.

classmethod render_option(value, label, options)[source]
class geonature.core.gn_permissions.admin.OptionQuerySelectField(*args, **kwargs)[source]

Bases: flask_admin.contrib.sqla.fields.QuerySelectField

Overrides the QuerySelectField class from flask admin to allow other attributes on a select option.

options_additional_values is added in form_args, it is a list of strings, each element is the name of the attribute in the model which will be added on the option

widget[source]
options_additional_values[source]
iter_choices()[source]

Provides data for choice widget rendering. Must return a sequence or iterable of (value, label, selected, render_kw) tuples.

class geonature.core.gn_permissions.admin.UserAjaxModelLoader(name: str, session: flask_admin.contrib.sqla._types.T_SESSION_OR_DB, model: type[flask_admin._types.T_SQLALCHEMY_MODEL], **options: Any)[source]

Bases: flask_admin.contrib.sqla.ajax.QueryAjaxModelLoader

Ajax related model loader. Override this to implement custom loading behavior.

format(user)[source]

Instead of returning a list of tuple (id, label), we return a list of tuple (id, label, excluded_availabilities). The third element of each tuple is the list of type of permissions the user already have, so it is useless to add this permission to the user, and they will be not available in the front select. Two remarks: - We only consider active permissions of the user - If the type of the permission allows two or more filters, we do not exclude it as it makes sens to add several

permissions of the same type with differents set of filters.

get_query()[source]
class geonature.core.gn_permissions.admin.AreaAjaxModelLoader(name: str, session: flask_admin.contrib.sqla._types.T_SESSION_OR_DB, model: type[flask_admin._types.T_SQLALCHEMY_MODEL], **options: Any)[source]

Bases: flask_admin.contrib.sqla.ajax.QueryAjaxModelLoader

Ajax related model loader. Override this to implement custom loading behavior.

format(area)[source]

Return (id, name) tuple from the model.

get_one(pk)[source]

Find model by its primary key.

Paramètres:

pk – Primary key value

get_query()[source]
get_list(term: str, offset: int = 0, limit: int = 10) Any[source]

Return models that match query.

Paramètres:
  • view – Administrative view.

  • query – Query string

  • offset – Offset

  • limit – Limit

class geonature.core.gn_permissions.admin.TaxrefAjaxModelLoader(name: str, session: flask_admin.contrib.sqla._types.T_SESSION_OR_DB, model: type[flask_admin._types.T_SQLALCHEMY_MODEL], **options: Any)[source]

Bases: flask_admin.contrib.sqla.ajax.QueryAjaxModelLoader

Ajax related model loader. Override this to implement custom loading behavior.

format(taxref)[source]

Return (id, name) tuple from the model.

get_query()[source]
get_one(pk)[source]

Find model by its primary key.

Paramètres:

pk – Primary key value

class geonature.core.gn_permissions.admin.ObjectAdmin(model: type[flask_admin._types.T_SQLALCHEMY_MODEL], session: flask_admin.contrib.sqla._types.T_SESSION_OR_DB, name: str | None = None, category: str | None = None, endpoint: str | None = None, url: str | None = None, static_folder: str | None = None, menu_class_name: str | None = None, menu_icon_type: str | None = None, menu_icon_value: str | None = None)[source]

Bases: geonature.core.admin.utils.CruvedProtectedMixin, flask_admin.contrib.sqla.ModelView

SQLAlchemy model view

Usage sample:

admin = Admin()
admin.add_view(ModelView(User, db.session))
module_code = 'ADMIN'[source]
object_code = 'PERMISSIONS'[source]
can_create = False[source]

Is model creation allowed

can_edit = False[source]

Is model editing allowed

can_delete = False[source]

Is model deletion allowed

column_list = ('code_object', 'description_object', 'modules')[source]

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

For example:

class MyModelView(BaseModelView):
    column_list = ('name', 'last_name', 'email')

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

class MyModelView(BaseModelView):
    column_list = ('name', User.last_name)
When using SQLAlchemy models, you can reference related columns like this::
class MyModelView(BaseModelView):

column_list = (“<relationship>.<related column name>”,)

column_labels[source]

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

For example:

class MyModelView(BaseModelView):
    column_labels = dict(name='Name', last_name='Last Name')
column_default_sort = 'id_object'[source]

Default sort column if no sorting is applied.

Example:

class MyModelView(BaseModelView):
    column_default_sort = 'user'

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

class MyModelView(BaseModelView):
    column_default_sort = ('user', True)

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

class MyModelView(BaseModelView):
    column_default_sort = [('name', True), ('last_name', True)]
column_formatters[source]

Dictionary of list view column formatters.

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

class MyModelView(BaseModelView):
    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

class MyModelView(BaseModelView):
    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
class geonature.core.gn_permissions.admin.PermissionAdmin(model: type[flask_admin._types.T_SQLALCHEMY_MODEL], session: flask_admin.contrib.sqla._types.T_SESSION_OR_DB, name: str | None = None, category: str | None = None, endpoint: str | None = None, url: str | None = None, static_folder: str | None = None, menu_class_name: str | None = None, menu_icon_type: str | None = None, menu_icon_value: str | None = None)[source]

Bases: geonature.core.admin.utils.CruvedProtectedMixin, flask_admin.contrib.sqla.ModelView

SQLAlchemy model view

Usage sample:

admin = Admin()
admin.add_view(ModelView(User, db.session))
module_code = 'ADMIN'[source]
object_code = 'PERMISSIONS'[source]
column_list = ('role', 'module', 'object', 'action', 'label', 'filters', 'expire_on')[source]

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

For example:

class MyModelView(BaseModelView):
    column_list = ('name', 'last_name', 'email')

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

class MyModelView(BaseModelView):
    column_list = ('name', User.last_name)
When using SQLAlchemy models, you can reference related columns like this::
class MyModelView(BaseModelView):

column_list = (“<relationship>.<related column name>”,)

column_labels[source]

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

For example:

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

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:

class PostAdmin(ModelView):
    column_select_related_list = (Post.user, Post.city)

Please refer to the subqueryload on list of possible values.

column_searchable_list = ('role.identifiant', 'role.nom_complet')[source]

Collection of the searchable columns.

Example:

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

You can also pass columns:

class MyModelView(ModelView):
    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.

column_formatters[source]

Dictionary of list view column formatters.

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

class MyModelView(BaseModelView):
    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

class MyModelView(BaseModelView):
    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
column_filters[source]

Collection of the column filters.

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

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

For example:

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

or:

from flask_admin.contrib.sqla.filters import BooleanEqualFilter

class MyModelView(BaseModelView):
    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'

class MyModelView(BaseModelView):
    column_filters = [
        FilterLastNameBrown(
            User.last_name, 'Last Name', options=(('1', 'Yes'), ('0', 'No'))
        )
    ]
named_filter_urls = True[source]

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.

column_sortable_list = (('role', 'role.nom_complet'), ('module', 'module.module_code'), ('object',...[source]

Collection of the sortable columns for the list view. If set to None, will get them from the model.

For example:

class MyModelView(BaseModelView):
    column_sortable_list = ('name', 'last_name')

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

class MyModelView(BaseModelView):
    column_sortable_list = ('name', ('user', 'user.username'))

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

class MyModelView(BaseModelView):
    column_sortable_list = (
        'name', ('user', ('user.first_name', 'user.last_name')))

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

class MyModelView(BaseModelView):
    column_sortable_list = ('name', ('user', User.username))
column_default_sort = [('role.nom_complet', False), ('module.module_code', False), ('object.code_object', False),...[source]

Default sort column if no sorting is applied.

Example:

class MyModelView(BaseModelView):
    column_default_sort = 'user'

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

class MyModelView(BaseModelView):
    column_default_sort = ('user', True)

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

class MyModelView(BaseModelView):
    column_default_sort = [('name', True), ('last_name', True)]
form_columns = ('role', 'availability', 'scope', 'sensitivity_filter', 'areas_filter', 'taxons_filter', 'expire_on')[source]

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

Example:

class MyModelView(BaseModelView):
    form_columns = ('name', 'email')

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

class MyModelView(BaseModelView):
    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.

form_overrides[source]

Dictionary of form column overrides.

Example:

class MyModelView(BaseModelView):
    form_overrides = dict(name=wtf.FileField)
form_args[source]

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

Example:

from wtforms.validators import DataRequired
class MyModelView(BaseModelView):
    form_args = dict(
        name=dict(label='First Name', validators=[DataRequired()])
    )
create_template = 'admin/hide_select2_options_create.html'[source]

Default create template

edit_template = 'admin/hide_select2_options_edit.html'[source]

Default edit template

form_ajax_refs[source]

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:

class MyModelView(BaseModelView):
    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:

class MyModelView(BaseModelView):
    form_ajax_refs = {
        '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.

get_query()[source]

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.

get_count_query()[source]

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.

render(template, **kwargs)[source]

Render template

Paramètres:
  • template – Template path to render

  • kwargs – Template arguments

create_form()[source]

Instantiate model creation form and return it.

Override to implement custom behavior.

class geonature.core.gn_permissions.admin.PermissionAvailableAdmin(model: type[flask_admin._types.T_SQLALCHEMY_MODEL], session: flask_admin.contrib.sqla._types.T_SESSION_OR_DB, name: str | None = None, category: str | None = None, endpoint: str | None = None, url: str | None = None, static_folder: str | None = None, menu_class_name: str | None = None, menu_icon_type: str | None = None, menu_icon_value: str | None = None)[source]

Bases: geonature.core.admin.utils.CruvedProtectedMixin, flask_admin.contrib.sqla.ModelView

SQLAlchemy model view

Usage sample:

admin = Admin()
admin.add_view(ModelView(User, db.session))
module_code = 'ADMIN'[source]
object_code = 'PERMISSIONS'[source]
can_create = False[source]

Is model creation allowed

can_delete = False[source]

Is model deletion allowed

can_export = False[source]

Is model list export allowed

column_labels[source]

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

For example:

class MyModelView(BaseModelView):
    column_labels = dict(name='Name', last_name='Last Name')
column_formatters[source]

Dictionary of list view column formatters.

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

class MyModelView(BaseModelView):
    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

class MyModelView(BaseModelView):
    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
column_sortable_list = (('module', 'module.module_code'), ('object', 'object.code_object'), ('action', 'action.code_action'))[source]

Collection of the sortable columns for the list view. If set to None, will get them from the model.

For example:

class MyModelView(BaseModelView):
    column_sortable_list = ('name', 'last_name')

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

class MyModelView(BaseModelView):
    column_sortable_list = ('name', ('user', 'user.username'))

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

class MyModelView(BaseModelView):
    column_sortable_list = (
        'name', ('user', ('user.first_name', 'user.last_name')))

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

class MyModelView(BaseModelView):
    column_sortable_list = ('name', ('user', User.username))
column_filters[source]

Collection of the column filters.

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

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

For example:

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

or:

from flask_admin.contrib.sqla.filters import BooleanEqualFilter

class MyModelView(BaseModelView):
    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'

class MyModelView(BaseModelView):
    column_filters = [
        FilterLastNameBrown(
            User.last_name, 'Last Name', options=(('1', 'Yes'), ('0', 'No'))
        )
    ]
column_default_sort = [('module.module_code', False), ('object.code_object', False), ('id_action', False)][source]

Default sort column if no sorting is applied.

Example:

class MyModelView(BaseModelView):
    column_default_sort = 'user'

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

class MyModelView(BaseModelView):
    column_default_sort = ('user', True)

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

class MyModelView(BaseModelView):
    column_default_sort = [('name', True), ('last_name', True)]
form_columns = ('scope_filter', 'sensitivity_filter', 'areas_filter', 'taxons_filter')[source]

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

Example:

class MyModelView(BaseModelView):
    form_columns = ('name', 'email')

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

class MyModelView(BaseModelView):
    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.

class geonature.core.gn_permissions.admin.RolePermAdmin(model: type[flask_admin._types.T_SQLALCHEMY_MODEL], session: flask_admin.contrib.sqla._types.T_SESSION_OR_DB, name: str | None = None, category: str | None = None, endpoint: str | None = None, url: str | None = None, static_folder: str | None = None, menu_class_name: str | None = None, menu_icon_type: str | None = None, menu_icon_value: str | None = None)[source]

Bases: geonature.core.admin.utils.CruvedProtectedMixin, flask_admin.contrib.sqla.ModelView

SQLAlchemy model view

Usage sample:

admin = Admin()
admin.add_view(ModelView(User, db.session))
module_code = 'ADMIN'[source]
object_code = 'PERMISSIONS'[source]
can_create = False[source]

Is model creation allowed

can_edit = False[source]

Is model editing allowed

can_delete = False[source]

Is model deletion allowed

can_export = False[source]

Is model list export allowed

can_view_details = True[source]

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

details_template = 'role_or_group_detail.html'[source]

Default details view template

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:

class PostAdmin(ModelView):
    column_select_related_list = (Post.user, Post.city)

Please refer to the subqueryload on list of possible values.

column_labels[source]

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

For example:

class MyModelView(BaseModelView):
    column_labels = dict(name='Name', last_name='Last Name')
column_searchable_list = ('identifiant', 'nom_complet')[source]

Collection of the searchable columns.

Example:

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

You can also pass columns:

class MyModelView(ModelView):
    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.

column_formatters[source]

Dictionary of list view column formatters.

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

class MyModelView(BaseModelView):
    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

class MyModelView(BaseModelView):
    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
column_formatters_detail[source]

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

Defaults to column_formatters when set to None.

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

get_query()[source]

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.

get_count_query()[source]

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.

class geonature.core.gn_permissions.admin.GroupPermAdmin(model: type[flask_admin._types.T_SQLALCHEMY_MODEL], session: flask_admin.contrib.sqla._types.T_SESSION_OR_DB, name: str | None = None, category: str | None = None, endpoint: str | None = None, url: str | None = None, static_folder: str | None = None, menu_class_name: str | None = None, menu_icon_type: str | None = None, menu_icon_value: str | None = None)[source]

Bases: RolePermAdmin

SQLAlchemy model view

Usage sample:

admin = Admin()
admin.add_view(ModelView(User, db.session))
column_list = ('nom_role', 'permissions_count')[source]

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

For example:

class MyModelView(BaseModelView):
    column_list = ('name', 'last_name', 'email')

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

class MyModelView(BaseModelView):
    column_list = ('name', User.last_name)
When using SQLAlchemy models, you can reference related columns like this::
class MyModelView(BaseModelView):

column_list = (“<relationship>.<related column name>”,)

column_details_list = ('nom_role', 'permissions_count', 'permissions')[source]

Collection of the field names included in the details view. If set to None, will get them from the model.

get_query()[source]

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.

get_count_query()[source]

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.

class geonature.core.gn_permissions.admin.UserPermAdmin(model: type[flask_admin._types.T_SQLALCHEMY_MODEL], session: flask_admin.contrib.sqla._types.T_SESSION_OR_DB, name: str | None = None, category: str | None = None, endpoint: str | None = None, url: str | None = None, static_folder: str | None = None, menu_class_name: str | None = None, menu_icon_type: str | None = None, menu_icon_value: str | None = None)[source]

Bases: RolePermAdmin

SQLAlchemy model view

Usage sample:

admin = Admin()
admin.add_view(ModelView(User, db.session))
column_list = ('identifiant', 'nom_role', 'prenom_role', 'groups', 'permissions_count')[source]

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

For example:

class MyModelView(BaseModelView):
    column_list = ('name', 'last_name', 'email')

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

class MyModelView(BaseModelView):
    column_list = ('name', User.last_name)
When using SQLAlchemy models, you can reference related columns like this::
class MyModelView(BaseModelView):

column_list = (“<relationship>.<related column name>”,)

column_labels[source]

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

For example:

class MyModelView(BaseModelView):
    column_labels = dict(name='Name', last_name='Last Name')
column_details_list = ('identifiant', 'nom_role', 'prenom_role', 'groups', 'permissions_count', 'permissions')[source]

Collection of the field names included in the details view. If set to None, will get them from the model.

get_query()[source]

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.

get_count_query()[source]

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.