wuttaweb.views.master

Base Logic for Master Views

class wuttaweb.views.master.MasterView(request, context=None)[source]

Base class for “master” views.

Master views typically map to a table in a DB, though not always. They essentially are a set of CRUD views for a certain type of data record.

Many attributes may be overridden in subclass. For instance to define model_class:

from wuttaweb.views import MasterView
from wuttjamaican.db.model import Person

class MyPersonView(MasterView):
    model_class = Person

def includeme(config):
    MyPersonView.defaults(config)

Note

Many of these attributes will only exist if they have been explicitly defined in a subclass. There are corresponding get_xxx() methods which should be used instead of accessing these attributes directly.

model_class

Optional reference to a data model class. While not strictly required, most views will set this to a SQLAlchemy mapped class, e.g. Person.

Code should not access this directly but instead call get_model_class().

model_name

Optional override for the view’s data model name, e.g. 'WuttaWidget'.

Code should not access this directly but instead call get_model_name().

model_name_normalized

Optional override for the view’s “normalized” data model name, e.g. 'wutta_widget'.

Code should not access this directly but instead call get_model_name_normalized().

model_title

Optional override for the view’s “humanized” (singular) model title, e.g. "Wutta Widget".

Code should not access this directly but instead call get_model_title().

model_title_plural

Optional override for the view’s “humanized” (plural) model title, e.g. "Wutta Widgets".

Code should not access this directly but instead call get_model_title_plural().

model_key

Optional override for the view’s “model key” - e.g. 'id' (string for simple case) or composite key such as ('id_field', 'name_field').

If model_class is set to a SQLAlchemy mapped class, the model key can be determined automatically.

Code should not access this directly but instead call get_model_key().

grid_key

Optional override for the view’s grid key, e.g. 'widgets'.

Code should not access this directly but instead call get_grid_key().

config_title

Optional override for the view’s “config” title, e.g. "Wutta Widgets" (to be displayed as Configure Wutta Widgets).

Code should not access this directly but instead call get_config_title().

route_prefix

Optional override for the view’s route prefix, e.g. 'wutta_widgets'.

Code should not access this directly but instead call get_route_prefix().

permission_prefix

Optional override for the view’s permission prefix, e.g. 'wutta_widgets'.

Code should not access this directly but instead call get_permission_prefix().

url_prefix

Optional override for the view’s URL prefix, e.g. '/widgets'.

Code should not access this directly but instead call get_url_prefix().

template_prefix

Optional override for the view’s template prefix, e.g. '/widgets'.

Code should not access this directly but instead call get_template_prefix().

listable

Boolean indicating whether the view model supports “listing” - i.e. it should have an index() view. Default value is True.

has_grid

Boolean indicating whether the index() view should include a grid. Default value is True.

grid_columns

List of columns for the index() view grid.

This is optional; see also get_grid_columns().

grid_row_class(obj, data, i)

This method is not defined on the MasterView base class; however if a subclass defines it then it will be automatically used to provide row_class for the main index() grid.

For more info see get_row_class().

filterable

Boolean indicating whether the grid for the index() view should allow filtering of data. Default is True.

This is used by make_model_grid() to set the grid’s filterable flag.

filter_defaults

Optional dict of default filter state.

This is used by make_model_grid() to set the grid’s filter_defaults.

Only relevant if filterable is true.

sortable

Boolean indicating whether the grid for the index() view should allow sorting of data. Default is True.

This is used by make_model_grid() to set the grid’s sortable flag.

See also sort_on_backend and sort_defaults.

sort_on_backend

Boolean indicating whether the grid data for the index() view should be sorted on the backend. Default is True.

This is used by make_model_grid() to set the grid’s sort_on_backend flag.

Only relevant if sortable is true.

sort_defaults

Optional list of default sorting info. Applicable for both frontend and backend sorting.

This is used by make_model_grid() to set the grid’s sort_defaults.

Only relevant if sortable is true.

paginated

Boolean indicating whether the grid data for the index() view should be paginated. Default is True.

This is used by make_model_grid() to set the grid’s paginated flag.

paginate_on_backend

Boolean indicating whether the grid data for the index() view should be paginated on the backend. Default is True.

This is used by make_model_grid() to set the grid’s paginate_on_backend flag.

creatable

Boolean indicating whether the view model supports “creating” - i.e. it should have a create() view. Default value is True.

viewable

Boolean indicating whether the view model supports “viewing” - i.e. it should have a view() view. Default value is True.

editable

Boolean indicating whether the view model supports “editing” - i.e. it should have an edit() view. Default value is True.

See also is_editable().

deletable

Boolean indicating whether the view model supports “deleting” - i.e. it should have a delete() view. Default value is True.

See also is_deletable().

deletable_bulk

Boolean indicating whether the view model supports “bulk deleting” - i.e. it should have a delete_bulk() view. Default value is False.

See also deletable_bulk_quick.

deletable_bulk_quick

Boolean indicating whether the view model supports “quick” bulk deleting, i.e. the operation is reliably quick enough that it should happen synchronously with no progress indicator.

Default is False in which case a progress indicator is shown while the bulk deletion is performed.

Only relevant if deletable_bulk is true.

form_fields

List of fields for the model form.

This is optional; see also get_form_fields().

has_autocomplete

Boolean indicating whether the view model supports “autocomplete” - i.e. it should have an autocomplete() view. Default is False.

downloadable

Boolean indicating whether the view model supports “downloading” - i.e. it should have a download() view. Default is False.

executable

Boolean indicating whether the view model supports “executing” - i.e. it should have an execute() view. Default is False.

configurable

Boolean indicating whether the master view supports “configuring” - i.e. it should have a configure() view. Default value is False.

autocomplete()[source]

View which accepts a single term param, and returns a JSON list of autocomplete results to match.

By default, this view is included only if has_autocomplete is true. It usually maps to a URL like /widgets/autocomplete.

Subclass generally does not need to override this method, but rather should override the others which this calls:

autocomplete_data(term)[source]

Should return the data/query for the “matching” model records, based on autocomplete search term. This is called by autocomplete().

Subclass must override this; default logic returns no data.

Parameters:

term – String search term as-is from user, e.g. “foo bar”.

Returns:

List of data records, or SQLAlchemy query.

autocomplete_normalize(obj)[source]

Should return a “normalized” version of the given model record, suitable for autocomplete JSON results. This is called by autocomplete().

Subclass may need to override this; default logic is simplistic but will work for basic models. It returns the “autocomplete results” dict for the object:

{
    'value': obj.uuid,
    'label': str(obj),
}

The 2 keys shown are required; any other keys will be ignored by the view logic but may be useful on the frontend widget.

Parameters:

obj – Model record/instance.

Returns:

Dict of “autocomplete results” format, as shown above.

collect_labels()[source]

Collect all labels defined by the view class and/or its parents.

A master view can declare labels via class-level attribute, like so:

from wuttaweb.views import MasterView

class WidgetView(MasterView):

    labels = {
        'id': "Widget ID",
        'serial_no': "Serial Number",
    }

All such labels, defined by any class from which the master view inherits, will be returned. However if the same label key is defined by multiple classes, the “subclass” always wins.

Labels defined in this way will apply to both forms and grids. See also set_labels().

Returns:

Dict of all labels found.

configure(session=None)[source]

View for configuring aspects of the app which are pertinent to this master view and/or model.

By default, this view is included only if configurable is true. It usually maps to a URL like /widgets/configure.

The expected workflow is as follows:

  • user navigates to Configure page

  • user modifies settings and clicks Save

  • this view then deletes all “known” settings

  • then it saves user-submitted settings

That is unless remove_settings is requested, in which case settings are deleted but then none are saved. The “known” settings by default include only the “simple” settings.

As a general rule, a particular setting should be configurable by (at most) one master view. Some settings may never be exposed at all. But when exposing a setting, careful thought should be given to where it logically/best belongs.

Some settings are “simple” and a master view subclass need only provide their basic definitions via configure_get_simple_settings(). If complex settings are needed, subclass must override one or more other methods to achieve the aim(s).

See also related methods, used by this one:

configure_form(form)[source]

Configure the given model form, as needed.

This is called by make_model_form() - for multiple CRUD views (create, view, edit, delete, possibly others).

The default logic here does just one thing: when “editing” (i.e. in edit() view) then all fields which are part of the model_key will be marked via set_readonly() so the user cannot change primary key values for a record.

Subclass may override as needed. The form param will already be “complete” and ready to use as-is, but this method can further modify it based on request details etc.

configure_gather_settings(data, simple_settings=None)[source]

Collect the full set of “normalized” settings from user request, so that configure() can save them.

Settings are gathered from the given request (e.g. POST) data, but also taking into account what we know based on the simple setting definitions.

Subclass may need to override this method if complex settings are required.

Parameters:
  • data – Form data submitted via POST request.

  • simple_settings – Optional list of simple settings, if already initialized. Otherwise it is retrieved via configure_get_simple_settings().

This method must return a list of normalized settings, similar in spirit to the definition syntax used in configure_get_simple_settings(). However the format returned here is minimal and contains just name/value:

{
    'name': 'wutta.app_title',
    'value': 'Wutta Wutta',
}

Note that the value will always be a string.

Also note, whereas it’s possible data will not contain all known settings, the return value should (potentially) contain all of them.

The one exception is when a simple setting has null value, by default it will not be included in the result (hence, not saved to DB) unless the setting definition has the save_if_empty flag set.

configure_get_context(simple_settings=None)[source]

Returns the full context dict, for rendering the configure() page template.

Default context will include simple_settings (normalized to just name/value).

You may need to override this method, to add additional “complex” settings etc.

Parameters:

simple_settings – Optional list of simple settings, if already initialized. Otherwise it is retrieved via configure_get_simple_settings().

Returns:

Context dict for the page template.

configure_get_simple_settings()[source]

This should return a list of “simple” setting definitions for the configure() view, which can be handled in a more automatic way. (This is as opposed to some settings which are more complex and must be handled manually; those should not be part of this method’s return value.)

Basically a “simple” setting is one which can be represented by a single field/widget on the Configure page.

The setting definitions returned must each be a dict of “attributes” for the setting. For instance a very simple setting might be:

{'name': 'wutta.app_title'}

The name is required, everything else is optional. Here is a more complete example:

{
    'name': 'wutta.production',
    'type': bool,
    'default': False,
    'save_if_empty': False,
}

Note that if specified, the default should be of the same data type as defined for the setting (bool in the above example). The default type is str.

Normally if a setting’s value is effectively null, the setting is removed instead of keeping it in the DB. This behavior can be changed per-setting via the save_if_empty flag.

Returns:

List of setting definition dicts as described above. Note that their order does not matter since the template must explicitly define field layout etc.

configure_grid(grid)[source]

Configure the grid for the index() view.

This is called by make_model_grid().

There is no default logic here; subclass should override as needed. The grid param will already be “complete” and ready to use as-is, but this method can further modify it based on request details etc.

configure_remove_settings(simple_settings=None, session=None)[source]

Remove all “known” settings from the DB; this is called by configure().

The point of this method is to ensure all “known” settings which are managed by this master view, are purged from the DB.

The default logic can handle this automatically for simple settings; subclass must override for any complex settings.

Parameters:

simple_settings – Optional list of simple settings, if already initialized. Otherwise it is retrieved via configure_get_simple_settings().

configure_save_settings(settings, session=None)[source]

Save the given settings to the DB; this is called by configure().

This method expects a list of name/value dicts and will simply save each to the DB, with no “conversion” logic.

Parameters:

settings – List of normalized setting definitions, as returned by configure_gather_settings().

create()[source]

View to “create” a new model record.

This usually corresponds to a URL like /widgets/new.

By default, this view is included only if creatable is true.

The default “create” view logic will show a form with field widgets, allowing user to submit new values which are then persisted to the DB (assuming typical SQLAlchemy model).

Subclass normally should not override this method, but rather one of the related methods which are called (in)directly by this one:

create_save_form(form)[source]

This method is responsible for “converting” the validated form data to a model instance, and then “saving” the result, e.g. to DB. It is called by create().

Subclass may override this, or any of the related methods called by this one:

Returns:

Should return the resulting model instance, e.g. as produced by objectify().

classmethod defaults(config)[source]

Provide default Pyramid configuration for a master view.

This is generally called from within the module’s includeme() function, e.g.:

from wuttaweb.views import MasterView

class WidgetView(MasterView):
    model_name = 'Widget'

def includeme(config):
    WidgetView.defaults(config)
Parameters:

config – Reference to the app’s pyramid.config.Configurator instance.

delete()[source]

View to delete an existing model instance.

This usually corresponds to a URL like /widgets/XXX/delete where XXX represents the key/ID for the record.

By default, this view is included only if deletable is true.

The default “delete” view logic will show a “psuedo-readonly” form with no fields editable, but with a submit button so user must confirm, before deletion actually occurs.

Subclass normally should not override this method, but rather one of the related methods which are called (in)directly by this one:

delete_bulk()[source]

View to delete all records in the current index() grid data set, i.e. those matching current query.

This usually corresponds to a URL like /widgets/delete-bulk.

By default, this view is included only if deletable_bulk is true.

This view requires POST method. When it is finished deleting, user is redirected back to index() view.

Subclass normally should not override this method, but rather one of the related methods which are called (in)directly by this one:

delete_bulk_action(data, progress=None)[source]

This method performs the actual bulk deletion, for the given data set. This is called via delete_bulk().

Default logic will call is_deletable() for every data record, and if that returns true then it calls delete_instance(). A progress indicator will be updated if one is provided.

Subclass should override if needed.

delete_instance(obj)[source]

Delete the given model instance.

As of yet there is no default logic for this method; it will raise NotImplementedError. Subclass should override if needed.

This method is called by delete_save_form().

delete_save_form(form)[source]

Perform the delete operation(s) based on the given form data.

Default logic simply calls delete_instance() on the form’s model_instance.

This method is called by delete() after it has validated the form.

download()[source]

View to download a file associated with a model record.

This usually corresponds to a URL like /widgets/XXX/download where XXX represents the key/ID for the record.

By default, this view is included only if downloadable is true.

This method will (try to) locate the file on disk, and return it as a file download response to the client.

The GET request for this view may contain a filename query string parameter, which can be used to locate one of various files associated with the model record. This filename is passed to download_path() for locating the file.

For instance: /widgets/XXX/download?filename=widget-specs.txt

Subclass normally should not override this method, but rather one of the related methods which are called (in)directly by this one:

download_path(obj, filename)[source]

Should return absolute path on disk, for the given object and filename. Result will be used to return a file response to client. This is called by download().

Default logic always returns None; subclass must override.

Parameters:
  • obj – Refefence to the model instance.

  • filename – Name of file for which to retrieve the path.

Returns:

Path to file, or None if not found.

Note that filename may be None in which case the “default” file path should be returned, if applicable.

If this method returns None (as it does by default) then the download() view will return a 404 not found response.

edit()[source]

View to “edit” details of an existing model record.

This usually corresponds to a URL like /widgets/XXX/edit where XXX represents the key/ID for the record.

By default, this view is included only if editable is true.

The default “edit” view logic will show a form with field widgets, allowing user to modify and submit new values which are then persisted to the DB (assuming typical SQLAlchemy model).

Subclass normally should not override this method, but rather one of the related methods which are called (in)directly by this one:

edit_save_form(form)[source]

This method is responsible for “converting” the validated form data to a model instance, and then “saving” the result, e.g. to DB. It is called by edit().

Subclass may override this, or any of the related methods called by this one:

Returns:

Should return the resulting model instance, e.g. as produced by objectify().

execute()[source]

View to “execute” a model record. Requires a POST request.

This usually corresponds to a URL like /widgets/XXX/execute where XXX represents the key/ID for the record.

By default, this view is included only if executable is true.

Probably this is a “rare” view to implement for a model. But there are two notable use cases so far, namely:

The general idea is to take some “irrevocable” action associated with the model record. In the case of upgrades, it is to run the upgrade script. For batches it is to “push live” the data held within the batch.

Subclass normally should not override this method, but rather one of the related methods which are called (in)directly by this one:

execute_instance(obj, user, progress=None)[source]

Perform the actual “execution” logic for a model record. Called by execute().

This method does nothing by default; subclass must override.

Parameters:
  • obj – Reference to the model instance.

  • user – Reference to the User who is doing the execute.

  • progress – Optional progress indicator factory.

get_action_url(action, obj, **kwargs)[source]

Generate an “action” URL for the given model instance.

This is a shortcut which generates a route name based on get_route_prefix() and the action param.

It returns the URL based on generated route name and object’s model key values.

Parameters:
  • action – String name for the action, which corresponds to part of some named route, e.g. 'view' or 'edit'.

  • obj – Model instance object.

get_action_url_delete(obj, i)[source]

Returns the “delete” grid action URL for the given object, if applicable.

Most typically this is like /widgets/XXX/delete where XXX represents the object’s key/ID.

This first calls is_deletable() and if that is false, this method will return None.

Calls get_action_url() to generate the true URL.

get_action_url_edit(obj, i)[source]

Returns the “edit” grid action URL for the given object, if applicable.

Most typically this is like /widgets/XXX/edit where XXX represents the object’s key/ID.

This first calls is_editable() and if that is false, this method will return None.

Calls get_action_url() to generate the true URL.

get_action_url_view(obj, i)[source]

Returns the “view” grid action URL for the given object.

Most typically this is like /widgets/XXX where XXX represents the object’s key/ID.

Calls get_action_url() under the hood.

get_class_hierarchy(topfirst=True)[source]

Convenience to return a list of classes from which the current class inherits.

This is a wrapper around wuttjamaican.util.get_class_hierarchy().

classmethod get_config_title()[source]

Returns the “config title” for the view/model.

The config title is used for page title in the configure() view, as well as links to it. It is usually plural, e.g. "Wutta Widgets" in which case that winds up being displayed in the web app as: Configure Wutta Widgets

The default logic will call get_model_title_plural() and return that as-is. A subclass may override by assigning config_title.

get_fallback_templates(template)[source]

Returns a list of “fallback” template paths which may be attempted for rendering a view. This is used within render_to_response() if the “first guess” template file was not found.

Parameters:

template – Base name for a template (without prefix), e.g. 'custom'.

Returns:

List of full template paths to be tried, based on the specified template. For instance if template is 'custom' this will (by default) return:

['/master/custom.mako']

get_form_fields()[source]

Returns the initial list of field names for the model form.

This is called by make_model_form(); in the resulting Form instance, this becomes fields.

This method may return None, in which case the form may (try to) generate its own default list.

Subclass may define form_fields for simple cases, or can override this method if needed.

Note that configure_form() may be used to further modify the final field list, regardless of what this method returns. So a common pattern is to declare all “supported” fields by setting form_fields but then optionally remove or replace some in configure_form().

get_grid_columns()[source]

Returns the default list of grid column names, for the index() view.

This is called by make_model_grid(); in the resulting Grid instance, this becomes columns.

This method may return None, in which case the grid may (try to) generate its own default list.

Subclass may define grid_columns for simple cases, or can override this method if needed.

Also note that configure_grid() may be used to further modify the final column set, regardless of what this method returns. So a common pattern is to declare all “supported” columns by setting grid_columns but then optionally remove or replace some of those within configure_grid().

get_grid_data(columns=None, session=None)[source]

Returns the grid data for the index() view.

This is called by make_model_grid(); in the resulting Grid instance, this becomes data.

Default logic will call get_query() and if successful, return the list from query.all(). Otherwise returns an empty list. Subclass should override as needed.

classmethod get_grid_key()[source]

Returns the (presumably) unique key to be used for the primary grid in the index() view. This key may also be used as the basis (key prefix) for secondary grids.

This is called from make_model_grid(); in the resulting Grid instance, this becomes key.

The default logic for this method will call get_route_prefix() and return that value as-is. A subclass may override by assigning grid_key.

get_index_title()[source]

Returns the main index title for the master view.

By default this returns the value from get_model_title_plural(). Subclass may override as needed.

get_index_url(**kwargs)[source]

Returns the URL for master’s index() view.

NB. this returns None if listable is false.

get_instance(session=None, matchdict=None)[source]

This should return the appropriate model instance, based on the matchdict of model keys.

Normally this is called with no arguments, in which case the pyramid.request.Request.matchdict is used, and will return the “current” model instance based on the request (route/params).

If a matchdict is provided then that is used instead, to obtain the model keys. In the simple/common example of a “native” model in WuttaWeb, this would look like:

keys = {'uuid': '38905440630d11ef9228743af49773a4'}
obj = self.get_instance(matchdict=keys)

Although some models may have different, possibly composite key names to use instead. The specific keys this logic is expecting are the same as returned by get_model_key().

If this method is unable to locate the instance, it should raise a 404 error, i.e. notfound().

Default implementation of this method should work okay for views which define a model_class. For other views however it will raise NotImplementedError, so subclass may need to define.

Warning

If you are defining this method for a subclass, please note this point regarding the 404 “not found” logic.

It is not enough to simply return this 404 response, you must explicitly raise the error. For instance:

def get_instance(self, **kwargs):

    # ..try to locate instance..
    obj = self.locate_instance_somehow()

    if not obj:

        # NB. THIS MAY NOT WORK AS EXPECTED
        #return self.notfound()

        # nb. should always do this in get_instance()
        raise self.notfound()

This lets calling code not have to worry about whether or not this method might return None. It can safely assume it will get back a model instance, or else a 404 will kick in and control flow goes elsewhere.

get_instance_title(instance)[source]

Return the human-friendly “title” for the instance, to be used in the page title when viewing etc.

Default logic returns the value from str(instance); subclass may override if needed.

classmethod get_instance_url_prefix()[source]

Generate the URL prefix specific to an instance for this model view. This will include model key param placeholders; it winds up looking like:

  • /widgets/{uuid}

  • /resources/{foo}|{bar}|{baz}

The former being the most simple/common, and the latter showing what a “composite” model key looks like, with pipe symbols separating the key parts.

classmethod get_model_class()[source]

Returns the model class for the view (if defined).

A model class will usually be a SQLAlchemy mapped class, e.g. Person.

There is no default value here, but a subclass may override by assigning model_class.

Note that the model class is not required - however if you do not set the model_class, then you must set the model_name.

classmethod get_model_key()[source]

Returns the “model key” for the master view.

This should return a tuple containing one or more “field names” corresponding to the primary key for data records.

In the most simple/common scenario, where the master view represents a Wutta-based SQLAlchemy model, the return value for this method is: ('uuid',)

But there is no “sane” default for other scenarios, in which case subclass should define model_key. If the model key cannot be determined, raises AttributeError.

Returns:

Tuple of field names comprising the model key.

classmethod get_model_name()[source]

Returns the model name for the view.

A model name should generally be in the format of a Python class name, e.g. 'WuttaWidget'. (Note this is singular, not plural.)

The default logic will call get_model_class() and return that class name as-is. A subclass may override by assigning model_name.

classmethod get_model_name_normalized()[source]

Returns the “normalized” model name for the view.

A normalized model name should generally be in the format of a Python variable name, e.g. 'wutta_widget'. (Note this is singular, not plural.)

The default logic will call get_model_name() and simply lower-case the result. A subclass may override by assigning model_name_normalized.

classmethod get_model_title()[source]

Returns the “humanized” (singular) model title for the view.

The model title will be displayed to the user, so should have proper grammar and capitalization, e.g. "Wutta Widget". (Note this is singular, not plural.)

The default logic will call get_model_name() and use the result as-is. A subclass may override by assigning model_title.

classmethod get_model_title_plural()[source]

Returns the “humanized” (plural) model title for the view.

The model title will be displayed to the user, so should have proper grammar and capitalization, e.g. "Wutta Widgets". (Note this is plural, not singular.)

The default logic will call get_model_title() and simply add a 's' to the end. A subclass may override by assigning model_title_plural.

classmethod get_permission_prefix()[source]

Returns the “permission prefix” for the master view. This prefix is used for all permissions defined by the view class.

For instance if permission prefix is 'widgets' then a view might have these permissions:

  • 'widgets.list'

  • 'widgets.create'

  • 'widgets.edit'

  • 'widgets.delete'

The default logic will call get_route_prefix() and use that value as-is. A subclass may override by assigning permission_prefix.

get_query(session=None)[source]

Returns the main SQLAlchemy query object for the index() view. This is called by get_grid_data().

Default logic for this method returns a “plain” query on the model_class if that is defined; otherwise None.

classmethod get_route_prefix()[source]

Returns the “route prefix” for the master view. This prefix is used for all named routes defined by the view class.

For instance if route prefix is 'widgets' then a view might have these routes:

  • 'widgets'

  • 'widgets.create'

  • 'widgets.edit'

  • 'widgets.delete'

The default logic will call get_model_name_normalized() and simply add an 's' to the end, making it plural. A subclass may override by assigning route_prefix.

classmethod get_template_prefix()[source]

Returns the “template prefix” for the master view. This prefix is used to guess which template path to render for a given view.

Using the same example as in get_url_prefix(), the template prefix would also be '/widgets' and the templates assumed for those routes would be:

  • /widgets/index.mako

  • /widgets/create.mako

  • /widgets/edit.mako

  • /widgets/delete.mako

The default logic will call get_url_prefix() and return that value as-is. A subclass may override by assigning template_prefix.

classmethod get_url_prefix()[source]

Returns the “URL prefix” for the master view. This prefix is used for all URLs defined by the view class.

Using the same example as in get_route_prefix(), the URL prefix would be '/widgets' and the view would have defined routes for these URLs:

  • /widgets/

  • /widgets/new

  • /widgets/XXX/edit

  • /widgets/XXX/delete

The default logic will call get_route_prefix() and simply add a '/' to the beginning. A subclass may override by assigning url_prefix.

grid_render_bool(record, key, value)[source]

Custom grid value renderer for “boolean” fields.

This converts a bool value to “Yes” or “No” - unless the value is None in which case this renders empty string. To use this feature for your grid:

grid.set_renderer('my_bool_field', self.grid_render_bool)
grid_render_currency(record, key, value, scale=2)[source]

Custom grid value renderer for “currency” fields.

This expects float or decimal values, and will round the decimal as appropriate, and add the currency symbol.

Parameters:

scale – Number of decimal digits to be displayed; default is 2 places.

To use this feature for your grid:

grid.set_renderer('my_currency_field', self.grid_render_currency)

# you can also override scale
grid.set_renderer('my_currency_field', self.grid_render_currency, scale=4)
grid_render_datetime(record, key, value, fmt=None)[source]

Custom grid value renderer for datetime fields.

Parameters:

fmt – Optional format string to use instead of the default: '%Y-%m-%d %I:%M:%S %p'

To use this feature for your grid:

grid.set_renderer('my_datetime_field', self.grid_render_datetime)

# you can also override format
grid.set_renderer('my_datetime_field', self.grid_render_datetime,
                  fmt='%Y-%m-%d %H:%M:%S')
grid_render_enum(record, key, value, enum=None)[source]

Custom grid value renderer for “enum” fields.

Parameters:

enum – Enum class for the field. This should be an instance of Enum.

To use this feature for your grid:

from enum import Enum

class MyEnum(Enum):
    ONE = 1
    TWO = 2
    THREE = 3

grid.set_renderer('my_enum_field', self.grid_render_enum, enum=MyEnum)
grid_render_notes(record, key, value, maxlen=100)[source]

Custom grid value renderer for “notes” fields.

If the given text value is shorter than maxlen characters, it is returned as-is.

But if it is longer, then it is truncated and an ellispsis is added. The resulting <span> tag is also given a title attribute with the original (full) text, so that appears on mouse hover.

To use this feature for your grid:

grid.set_renderer('my_notes_field', self.grid_render_notes)

# you can also override maxlen
grid.set_renderer('my_notes_field', self.grid_render_notes, maxlen=50)
has_any_perm(*names)[source]

Shortcut to check if current user has any of the given permissions.

This calls has_perm() until one returns True. If none do, returns False.

has_perm(name)[source]

Shortcut to check if current user has the given permission.

This will automatically add the permission_prefix to name before passing it on to has_perm().

For instance within the UserView these give the same result:

self.request.has_perm('users.edit')

self.has_perm('edit')

So this shortcut only applies to permissions defined for the current master view. The first example above must still be used to check for “foreign” permissions (i.e. any needing a different prefix).

index()[source]

View to “list” (filter/browse) the model data.

This is the “default” view for the model and is what user sees when visiting the “root” path under the url_prefix, e.g. /widgets/.

By default, this view is included only if listable is true.

The default view logic will show a “grid” (table) with the model data (unless has_grid is false).

See also related methods, which are called by this one:

is_deletable(obj)[source]

Returns a boolean indicating whether “delete” should be allowed for the given model instance (and for current user).

By default this always return True; subclass can override if needed.

Note that the use of this method implies deletable is true, so the method does not need to check that flag.

is_editable(obj)[source]

Returns a boolean indicating whether “edit” should be allowed for the given model instance (and for current user).

By default this always return True; subclass can override if needed.

Note that the use of this method implies editable is true, so the method does not need to check that flag.

make_button(label, variant=None, primary=False, **kwargs)[source]

Make and return a HTML <b-button> literal.

Parameters:
  • label – Text label for the button.

  • variant – This is the “Buefy type” (or “Oruga variant”) for the button. Buefy and Oruga represent this differently but this logic expects the Buefy format (e.g. is-danger) and not the Oruga format (e.g. danger), despite the param name matching Oruga’s terminology.

  • type – This param is not advertised in the method signature, but if caller specifies type instead of variant it should work the same.

  • primary

    If neither variant nor type are specified, this flag may be used to automatically set the Buefy type to is-primary.

    This is the preferred method where applicable, since it avoids the Buefy vs. Oruga confusion, and the implementation can change in the future.

  • **kwargs – All remaining kwargs are passed to the underlying HTML.tag() call, so will be rendered as attributes on the button tag.

Returns:

HTML literal for the button element. Will be something along the lines of:

<b-button type="is-primary"
          icon-pack="fas"
          icon-left="hand-pointer">
  Click Me
</b-button>

make_model_form(model_instance=None, **kwargs)[source]

Create and return a Form for the view model.

Note that this method is called for multiple “CRUD” views, e.g.:

See also related methods, which are called by this one:

make_model_grid(session=None, **kwargs)[source]

Create and return a Grid instance for use with the index() view.

See also related methods, which are called by this one:

make_progress(key, **kwargs)[source]

Create and return a SessionProgress instance, with the given key.

This is normally done just before calling render_progress().

objectify(form)[source]

Must return a “model instance” object which reflects the validated form data.

In simple cases this may just return the validated data dict.

When dealing with SQLAlchemy models it would return a proper mapped instance, creating it if necessary.

Parameters:

form – Reference to the already validated Form object. See the form’s validated attribute for the data.

See also edit_save_form() which calls this method.

persist(obj, session=None)[source]

If applicable, this method should persist (“save”) the given object’s data (e.g. to DB), creating or updating it as needed.

This is part of the “submit form” workflow; obj should be a model instance which already reflects the validated form data.

Note that there is no default logic here, subclass must override if needed.

Parameters:

obj – Model instance object as produced by objectify().

See also edit_save_form() which calls this method.

render_progress(progress, context=None, template=None)[source]

Render the progress page, with given template/context.

When a view method needs to start a long-running operation, it first starts a thread to do the work, and then it renders the “progress” page. As the operation continues the progress page is updated. When the operation completes (or fails) the user is redirected to the final destination.

TODO: should document more about how to do this..

Parameters:

progress – Progress indicator instance as returned by make_progress().

Returns:

A response with rendered progress page.

render_to_response(template, context)[source]

Locate and render an appropriate template, with the given context, and return a response.

The specified template should be only the “base name” for the template - e.g. 'index' or 'edit'. This method will then try to locate a suitable template file, based on values from get_template_prefix() and get_fallback_templates().

In practice this usually means two different template paths will be attempted, e.g. if template is 'edit' and template_prefix is '/widgets':

  • /widgets/edit.mako

  • /master/edit.mako

The first template found to exist will be used for rendering. It then calls pyramid.renderers.render_to_response() and returns the result.

Parameters:
  • template – Base name for the template.

  • context – Data dict to be used as template context.

Returns:

Response object containing the rendered template.

set_labels(obj)[source]

Set label overrides on a form or grid, based on what is defined by the view class and its parent class(es).

This is called automatically from configure_grid() and configure_form().

This calls collect_labels() to find everything, then it assigns the labels using one of (based on obj type):

Parameters:

obj – Either a Grid or a Form instance.

view()[source]

View to “view” details of an existing model record.

This usually corresponds to a URL like /widgets/XXX where XXX represents the key/ID for the record.

By default, this view is included only if viewable is true.

The default view logic will show a read-only form with field values displayed.

Subclass normally should not override this method, but rather one of the related methods which are called (in)directly by this one: