ferrosoft.apps.ferrobase.views package

Submodules

ferrosoft.apps.ferrobase.views.api_token module

class ferrosoft.apps.ferrobase.views.api_token.APITokenCreateView(*args, **kwargs)[source]

Bases: CreateView

Create an API token and reveal its secret value exactly once.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Api Token'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:apitoken_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

form_class

alias of APITokenForm

form_valid(form)[source]

If the form is valid, create the token using specialized function.

get_context_data(**kwargs)[source]

Expose secret_token so the template can display it once.

model

alias of APIToken

permission_required = ['ferrobase.add_apitoken']
template_name = 'ferrobase/api_token/create.html'
class ferrosoft.apps.ferrobase.views.api_token.APITokenReadView(**kwargs)[source]

Bases: TableView

Per-user listing of active/inactive API tokens.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Api Token'

Activity title should be a very short label e.g. indicating the current model being operated on.

create_view: str | Callable[[...], str] | None = 'ferrobase:apitoken_create'

List view displays a button to create a new object if create_view is not None.

filterset_class

alias of APITokenFilterSet

get_queryset()[source]

Scope the queryset to the current user and visible token statuses.

model

alias of APIToken

ordering = 'name'
permission_required = ['ferrobase.view_apitoken']
plural = 'API Tokens'

Plural may be used by templates to display the model name.

singular = 'API Token'

Singular may be used by templates to display the model name.

table_class

alias of APITokenTable

ferrosoft.apps.ferrobase.views.base module

ferrosoft.apps.ferrobase.views.base.render_ajax_result(request, success=False, message=None, template='ferrobase/ajax_result.html', **kwargs)[source]

Return response containing a fonticon and message. If message is None a standard message is displayed based on sucess.

Use in conjunction with ajax templatetags.

ferrosoft.apps.ferrobase.views.company_site module

class ferrosoft.apps.ferrobase.views.company_site.CompanySiteCreateView(**kwargs)[source]

Bases: CreateView

Create a company site, pre-populating code from the configured ID sequence.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Company Site'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:companysite_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

form_class

alias of CompanySiteForm

form_template = 'ferrobase/company_site/form.html'

Template to be included instead of generic form display.

get_form_kwargs()[source]

Generate the next COMPANY_SITE ID and inject it as form initial.

model

alias of CompanySite

permission_required = ['ferrobase.add_companysite']
class ferrosoft.apps.ferrobase.views.company_site.CompanySiteDeleteView(*args, **kwargs)[source]

Bases: DeleteView

Delete a company site, blocked when referenced by other records.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Company Site'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:companysite_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

model

alias of CompanySite

permission_required = ['ferrobase.delete_companysite']
class ferrosoft.apps.ferrobase.views.company_site.CompanySiteReadView(**kwargs)[source]

Bases: FilterView

Filterable list of company sites ordered by code.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Company Site'

Activity title should be a very short label e.g. indicating the current model being operated on.

create_view: str | Callable[[...], str] | None = 'ferrobase:companysite_create'

List view displays a button to create a new object if create_view is not None.

filterset_class

alias of CompanySiteFilterSet

model

alias of CompanySite

ordering = 'code'
permission_required = ['ferrobase.view_companysite']
plural = 'Company Sites'

Plural may be used by templates to display the model name.

singular = 'Company Site'

Singular may be used by templates to display the model name.

class ferrosoft.apps.ferrobase.views.company_site.CompanySiteUpdateView(**kwargs)[source]

Bases: UpdateView

Update a company site using the shared company-site form.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Company Site'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:companysite_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:companysite_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:companysite_delete'

Update view displays a button to delete the object if delete_view is not None.

form_class

alias of CompanySiteForm

form_template = 'ferrobase/company_site/form.html'

Template to be included instead of generic form display.

model

alias of CompanySite

permission_required = ['ferrobase.change_companysite']
plural = 'Company Sites'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:companysite_index'

Name of read view to link to in related links widget.

singular = 'Company Site'

Singular may be used by templates to display the model name.

ferrosoft.apps.ferrobase.views.files module

class ferrosoft.apps.ferrobase.views.files.DirectoryListingView(**kwargs)[source]

Bases: TableView

List files within a directory filtered by per-user access grants.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Files'

Activity title should be a very short label e.g. indicating the current model being operated on.

create_view: str | Callable[[...], str] | None = 'ferrobase:storedfile_create'

List view displays a button to create a new object if create_view is not None.

filterset_class

alias of StoredFileFilterSet

get_queryset()[source]

Union three access scopes (owner, organisation, public) for the directory.

The UNION is built from three filtered querysets — owner files bypass access grants entirely, while organisation- and public-scoped files require an explicit READ grant. .distinct() collapses duplicates introduced by the UNION.

help_topic: str | None = 'files'

ID of help topic passed to get_help_url. Resulting URL is added to template context as help_url.

model

alias of StoredFile

ordering = ['name']
permission_required = ['ferrobase.view_storedfile']
plural = 'Files'

Plural may be used by templates to display the model name.

singular = 'File'

Singular may be used by templates to display the model name.

table_class

alias of StoredFileTable

class ferrosoft.apps.ferrobase.views.files.DirectoryRootView(**kwargs)[source]

Bases: ListView

Top-level directory browser showing only root directories.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Files'

Activity title should be a very short label e.g. indicating the current model being operated on.

create_view: str | Callable[[...], str] | None = 'ferrobase:directory_create'

List view displays a button to create a new object if create_view is not None.

get_queryset()[source]

Restrict to directories without a parent (i.e. roots).

help_topic: str | None = 'files'

ID of help topic passed to get_help_url. Resulting URL is added to template context as help_url.

model

alias of Directory

ordering = ['name']
permission_required = ['ferrobase.view_directory']
plural = 'Folders'

Plural may be used by templates to display the model name.

singular = 'Folder'

Singular may be used by templates to display the model name.

class ferrosoft.apps.ferrobase.views.files.FileUpdateView(**kwargs)[source]

Bases: UpdateView

Rename a file and edit its access grants matrix.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'File'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:storedfile_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:storedfile_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:storedfile_delete'

Update view displays a button to delete the object if delete_view is not None.

fields = ['name']
get_context_data(**kwargs)[source]

Build the {subject: {mode: bool}} access matrix and download URL.

help_topic: str | None = 'files'

ID of help topic passed to get_help_url. Resulting URL is added to template context as help_url.

model

alias of StoredFile

permission_required = ['ferrobase.change_storedfile']
plural = 'Files'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:storedfile_index'

Name of read view to link to in related links widget.

singular = 'File'

Singular may be used by templates to display the model name.

template_name = 'ferrobase/storedfile/update.html'

ferrosoft.apps.ferrobase.views.generic module

Generic views defining a gold standard for Ferrosoft Platform.

Currently, these generic views revolve around CRUD for models. They spice up generic views found in Django, django-filter and django_tables2.

To make use of it, define subclasses for each CRUD verb to be supported:

  • Define a CreateView to create instances of a model class.

  • Define a UpdateView to update instances of a model class.

  • Define a DeleteView to delete instances of a model class.

  • Define one of the read views to read display instances of a model class:
    • Define a TableView to display a table along with filters.

    • Define a FilterView to display a list along with filters.

    • Define a ListView to display a list without filters.

In the same module where the subclasses are defined, call model_crud_routes to generate a list of URL patterns, which can be used in the app’s url module.

Example

class MaterialCreateView(generic.CreateView):

fields = [“code”, “name”] model = Material

class MaterialListView(generic.FilterView):

filterset_class = MaterialFilterSet model = Material ordering = “code”

class MaterialUpdateView(generic.UpdateView):

fields = [“code”, “name”] model = Material

class MaterialDeleteView(generic.DeleteView):

model = Material

material_urls = generic.model_crud_routes(

Material, create_view=MaterialCreateView, read_view=MaterialListView, update_view=MaterialUpdateView, delete_view=MaterialDeleteView,

)

class ferrosoft.apps.ferrobase.views.generic.ClassAttributes(attrs)[source]

Bases: object

Build view class attributes.

This is used internally by view metaclasses.

Attributes created via “add” methods are added as a default and can be overridden by user defined attributes.

add_actions(cancel_action=False, create_action=False, delete_action=False, read_action=False, copy_action=False)[source]

Add view attributes expected by ModelContextMixin.

Return type:

ClassAttributes

add_activity_view(*, title=None, app=None)[source]

Add attributes expected by ActivityViewMixin.

Return type:

ClassAttributes

add_designation()[source]

Add singular/plural attributes expected by ModelContextMixin.

Return type:

ClassAttributes

add_permission_required(verb)[source]

Add a default permission_required for verb on the view’s model.

Return type:

ClassAttributes

property attrs: dict[str, Any]

Combine default attributes created by “add” methods with user defined attributes.

User defined attributes overwrite default attributes.

require_all(*required)[source]

Require all named attributes be present.

Return type:

ClassAttributes

require_any(*required)[source]

Require at least one of the named attributes be present.

Return type:

ClassAttributes

class ferrosoft.apps.ferrobase.views.generic.CopyView(*args, **kwargs)[source]

Bases: LoginRequiredMixin, PermissionRequiredMixin, PlatformActivityMixin, ModelContextMixin, CreateView

Create-by-copy view: pre-populates the form from an existing source object.

The source_id URL kwarg identifies the record to clone. On GET the form is bound to the source instance so its values appear as defaults; on POST the instance is intentionally cleared so saving creates a new record instead of mutating the original.

abstract = True
get(request, *args, **kwargs)[source]

Load the source object then defer to Django’s GET handling.

get_context_data(**kwargs)[source]

Expose source_object so the template can display its identity.

get_form_initial()[source]

Pass the source_id to the form so it can record provenance.

get_form_kwargs()[source]

Bind the form to the source object on GET only, never on POST.

get_source_object()[source]

Look up the source record identified by the source_id URL kwarg.

post(request, *args, **kwargs)[source]

Load the source object then defer to Django’s POST handling.

template_name = 'ferrobase/bootstrap5/copy_view.html'
class ferrosoft.apps.ferrobase.views.generic.CopyViewMeta(name, bases, attrs, **kwargs)[source]

Bases: type

Metaclass that wires copy-specific defaults onto CopyView subclasses.

class ferrosoft.apps.ferrobase.views.generic.CreateView(**kwargs)[source]

Bases: LoginRequiredMixin, PermissionRequiredMixin, PlatformActivityMixin, ModelContextMixin, CreateView

Display and handle a form for creation of a model.

Required attributes:

model: Model class fields: Model field names form_class: Model form class (preferred over fields)

See also ModelContextMixin for optional attributes.

abstract = True
template_name = 'ferrobase/bootstrap5/create_view.html'
class ferrosoft.apps.ferrobase.views.generic.CreateViewMeta(name, bases, attrs, **kwargs)[source]

Bases: type

Conveniently add common attributes to CreateView classes.

class ferrosoft.apps.ferrobase.views.generic.DeleteView(*args, **kwargs)[source]

Bases: LoginRequiredMixin, PermissionRequiredMixin, PlatformActivityMixin, ModelContextMixin, DeleteView

Display and handle a form for deletion of a model.

Required attributes:

model: Model class

See also ModelContextMixin for optional attributes.

abstract = True
form_valid(form)[source]

Perform the delete, falling back to the form when on_delete=RESTRICT fires.

get_context_data(**kwargs)[source]

Expose deletion_restricted so the template can warn the user.

get_success_url()[source]

Redirect to the conventional <app>:<model>_index list view.

template_name = 'ferrobase/bootstrap5/delete_view.html'
class ferrosoft.apps.ferrobase.views.generic.DeleteViewMeta(name, bases, attrs, **kwargs)[source]

Bases: type

Conveniently add common attributes to DeleteView classes.

class ferrosoft.apps.ferrobase.views.generic.DependentCreateView(*args, **kwargs)[source]

Bases: CreateView

Create view that requires a parent object identified via a query param.

The parent is looked up using get_parent_kwargs() (defaulting to ?<parent_query>=<pk>). When the parent cannot be resolved and enable_missing_parent is False (default), the view returns a 404 page so the user is told the dependency is missing.

abstract = True
dispatch(request, *args, **kwargs)[source]

Resolve the parent object before dispatching to the base handler.

enable_missing_parent = False
get_parent_kwargs()[source]

Build the lookup kwargs for the parent (override for custom keys).

get_success_url()[source]

Redirect to the parent’s absolute URL after a successful create.

parent_model = None
parent_query = 'q'
class ferrosoft.apps.ferrobase.views.generic.DetailView(**kwargs)[source]

Bases: LoginRequiredMixin, PermissionRequiredMixin, PlatformActivityMixin, ModelContextMixin, DetailView

Display a single object.

The normal CRUD workflow uses UpdateView as the standard detail view for a given model. Use DetailView for specific tasks related to the model.

Required attributes:

model: Model class template_name: Template to render

abstract = True
template_name = 'ferrobase/bootstrap5/detail_view.html'
class ferrosoft.apps.ferrobase.views.generic.DetailViewMeta(name, bases, attrs, **kwargs)[source]

Bases: type

Conveniently add common attributes to DetailView classes.

class ferrosoft.apps.ferrobase.views.generic.FilterView(**kwargs)[source]

Bases: LoginRequiredMixin, PermissionRequiredMixin, PlatformActivityMixin, ModelContextMixin, FilterView

Display a list along with filters.

This is less useful as TableView, as it doesn’t support ordering of individual attributes. Prefer TableView over this class.

Required attributes:

model: Model class filterset_class: Filter set class ordering: Default ordering to ensure pagination works reliably.

See also ModelContextMixin for optional attributes.

abstract = True
paginate_by = 30
template_name = 'ferrobase/bootstrap5/filter_view.html'
class ferrosoft.apps.ferrobase.views.generic.FilterViewMeta(name, bases, attrs, **kwargs)[source]

Bases: type

Conveniently add common attributes to FilterView classes.

class ferrosoft.apps.ferrobase.views.generic.ListView(**kwargs)[source]

Bases: LoginRequiredMixin, PermissionRequiredMixin, PlatformActivityMixin, ModelContextMixin, ListView

Display a list.

This is the least useful read view, as it doesn’t support ordering nor filtering. Prefer other read views over this class.

Required attributes:

model: Model class ordering: Default ordering to ensure pagination works reliably.

See also ModelContextMixin for optional attributes.

abstract = True
paginate_by = 30
template_name = 'ferrobase/bootstrap5/list_view.html'
class ferrosoft.apps.ferrobase.views.generic.ListViewMeta(name, bases, attrs, **kwargs)[source]

Bases: type

Conveniently add common attributes to ListView classes.

class ferrosoft.apps.ferrobase.views.generic.ModelContextMixin[source]

Bases: ContextMixin

Add various template context variables related to model CRUD views.

cancel_view: str | Callable[[...], str] | None = None

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

copy_view: str | Callable[[...], str] | None = None

Update view displays a button to copy the object if copy_view is not None.

create_view: str | Callable[[...], str] | None = None

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = None

Update view displays a button to delete the object if delete_view is not None.

enable_filter_display: bool = True

Whether to display filters off-canvas (applicable to read views).

form_template = None

Template to be included instead of generic form display.

get_context_data(**kwargs)[source]

Add CRUD-related URLs, permission flags and related-links to the context.

is_allowed(verb)[source]

Check whether the current user holds verb permission on the model.

Return type:

bool

list_item_template = None

Template to be included instead of generic list item display.

multipart_form = False

Whether to use multipart/form-data enctype.

plural = None

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = None

Name of read view to link to in related links widget.

Related links to include in the context. The tuple must include an URL and label.

Whether to include a curated set of default related links in the context.

singular = None

Singular may be used by templates to display the model name.

ferrosoft.apps.ferrobase.views.generic.PAGE_SIZE = 30

Default page size for read views.

class ferrosoft.apps.ferrobase.views.generic.PlatformActivityMixin[source]

Bases: ContextMixin

Provide context about the current activity to the base template.

activity_app = None

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = ''

Activity title should be a very short label e.g. indicating the current model being operated on.

container_class = None

Classes for <main> container.

get_context_data(**kwargs)[source]

Inject activity metadata (title, app, container, help URL) into the context.

Raises:

RuntimeError – If neither activity_app nor a string template_name is defined and the app label cannot be inferred.

help_topic: str | None = None

ID of help topic passed to get_help_url. Resulting URL is added to template context as help_url.

class ferrosoft.apps.ferrobase.views.generic.TableView(**kwargs)[source]

Bases: LoginRequiredMixin, PermissionRequiredMixin, PlatformActivityMixin, ModelContextMixin, SingleTableMixin, FilterView

Display a single table along with filters.

This is the most featureful read view and should be preferred over others.

Required attributes:

model: Model class filterset_class: Filter set class table_class: Table class ordering: Default ordering to ensure pagination works reliably.

abstract = True
paginate_by = 30
template_name = 'ferrobase/bootstrap5/table_view.html'
class ferrosoft.apps.ferrobase.views.generic.TableViewMeta(name, bases, attrs, **kwargs)[source]

Bases: type

Conveniently add common attributes to TableView classes.

class ferrosoft.apps.ferrobase.views.generic.TemplateView(**kwargs)[source]

Bases: LoginRequiredMixin, PlatformActivityMixin, TemplateView

Login-required TemplateView pre-mixed with platform activity context.

class ferrosoft.apps.ferrobase.views.generic.UpdateView(**kwargs)[source]

Bases: LoginRequiredMixin, PermissionRequiredMixin, PlatformActivityMixin, ModelContextMixin, UpdateView

Display and handle a form for updating of a model.

Required attributes:

model: Model class fields: Model field names form_class: Model form class (preferred over fields)

See also ModelContextMixin for optional attributes.

abstract = True
add_copy_action = False

Show a button linking to copy view, if enabled.

Show default related links, if enabled.

template_name = 'ferrobase/bootstrap5/update_view.html'
class ferrosoft.apps.ferrobase.views.generic.UpdateViewMeta(name, bases, attrs, **kwargs)[source]

Bases: type

Conveniently add common attributes to UpdateView classes.

ferrosoft.apps.ferrobase.views.generic.model_crud_routes(model_class, create_view=None, read_view=None, update_view=None, delete_view=None, copy_view=None)[source]

Create URL patterns for model CRUD routes.

  • Read view name is {model_name}_index.

  • Create view name is {model_name}_create.

  • Update view name is {model_name}_update.

  • Delete view name is {model_name}_delete.

Model name is all lowercase, no underscores.

Return type:

List[URLPattern]

ferrosoft.apps.ferrobase.views.group module

Views for group management. Groups are used in the Django permission system.

class ferrosoft.apps.ferrobase.views.group.GroupCreateView(**kwargs)[source]

Bases: CreateView

Create an auth group; redirects to the update view on success.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Group'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:group_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

fields = ['name']
get_success_url()[source]

Send the user to the freshly-created group’s update page.

model

alias of Group

permission_required = ['auth.add_group']
class ferrosoft.apps.ferrobase.views.group.GroupDeleteView(*args, **kwargs)[source]

Bases: DeleteView

Delete an auth group.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Group'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:group_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

get_success_url()[source]

Return to the group list after deletion.

model

alias of Group

permission_required = ['auth.delete_group']
class ferrosoft.apps.ferrobase.views.group.GroupListView(**kwargs)[source]

Bases: ListView

List Django auth groups ordered by name.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Group'

Activity title should be a very short label e.g. indicating the current model being operated on.

create_view: str | Callable[[...], str] | None = 'ferrobase:group_create'

List view displays a button to create a new object if create_view is not None.

model

alias of Group

ordering = 'name'
permission_required = ['auth.view_group']
plural = 'groups'

Plural may be used by templates to display the model name.

singular = 'group'

Singular may be used by templates to display the model name.

class ferrosoft.apps.ferrobase.views.group.GroupPermissionsView(**kwargs)[source]

Bases: UpdateView

Manage the permission set attached to an auth group.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Group permissions'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:group_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:group_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:group_delete'

Update view displays a button to delete the object if delete_view is not None.

form_class

alias of GroupPermissionsForm

get_success_url()[source]

Return to the group’s update view after saving permissions.

model

alias of Group

permission_required = ['auth.change_group']
plural = 'groups'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:group_index'

Name of read view to link to in related links widget.

singular = 'group'

Singular may be used by templates to display the model name.

class ferrosoft.apps.ferrobase.views.group.GroupUpdateView(**kwargs)[source]

Bases: UpdateView

Rename an auth group.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Group'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:group_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:group_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:group_delete'

Update view displays a button to delete the object if delete_view is not None.

fields = ['name']
get_success_url()[source]

Stay on the same group’s update page after a successful save.

model

alias of Group

permission_required = ['auth.change_group']
plural = 'groups'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:group_index'

Name of read view to link to in related links widget.

singular = 'group'

Singular may be used by templates to display the model name.

template_name = 'ferrobase/group/update.html'

ferrosoft.apps.ferrobase.views.index module

class ferrosoft.apps.ferrobase.views.index.IndexView(**kwargs)[source]

Bases: TemplateView

Platform landing page that redirects to per-app home views when configured.

get(request, *args, **kwargs)[source]

Forward authenticated users to APP_META.home_view when set.

The tenant query parameter is preserved across the redirect so the target view stays scoped to the current tenant.

get_context_data(**kwargs)[source]

Add the static index menu and the settings menu for the current user.

get_template_names()[source]

Pick the dashboard for signed-in users and the public splash otherwise.

ferrosoft.apps.ferrobase.views.material module

class ferrosoft.apps.ferrobase.views.material.MaterialCopyView(*args, **kwargs)[source]

Bases: CopyView

Create a new material seeded from an existing one’s code + name.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Copy Material'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:material_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

form_class

alias of MaterialForm

model

alias of Material

permission_required = ['ferrobase.add_material']
class ferrosoft.apps.ferrobase.views.material.MaterialCreateView(**kwargs)[source]

Bases: CreateView

Create a material record (code + name).

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Material'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:material_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

fields = ['code', 'name']
help_topic: str | None = 'materials'

ID of help topic passed to get_help_url. Resulting URL is added to template context as help_url.

model

alias of Material

permission_required = ['ferrobase.add_material']
class ferrosoft.apps.ferrobase.views.material.MaterialDeleteView(*args, **kwargs)[source]

Bases: DeleteView

Delete a material, blocked when referenced by other records.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Material'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:material_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

help_topic: str | None = 'materials'

ID of help topic passed to get_help_url. Resulting URL is added to template context as help_url.

model

alias of Material

permission_required = ['ferrobase.delete_material']
class ferrosoft.apps.ferrobase.views.material.MaterialListView(**kwargs)[source]

Bases: FilterView

Filterable list of materials ordered by code.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Material'

Activity title should be a very short label e.g. indicating the current model being operated on.

create_view: str | Callable[[...], str] | None = 'ferrobase:material_create'

List view displays a button to create a new object if create_view is not None.

filterset_class

alias of MaterialFilterSet

help_topic: str | None = 'materials'

ID of help topic passed to get_help_url. Resulting URL is added to template context as help_url.

model

alias of Material

ordering = 'code'
permission_required = ['ferrobase.view_material']
plural = 'Materials'

Plural may be used by templates to display the model name.

singular = 'Material'

Singular may be used by templates to display the model name.

class ferrosoft.apps.ferrobase.views.material.MaterialUpdateView(**kwargs)[source]

Bases: UpdateView

Update a material; surfaces a Copy button via add_copy_action.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Material'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:material_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

copy_view: str | Callable[[...], str] | None = 'ferrobase:material_copy'

Update view displays a button to copy the object if copy_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:material_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:material_delete'

Update view displays a button to delete the object if delete_view is not None.

fields = ['code', 'name']
help_topic: str | None = 'materials'

ID of help topic passed to get_help_url. Resulting URL is added to template context as help_url.

model

alias of Material

permission_required = ['ferrobase.change_material']
plural = 'Materials'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:material_index'

Name of read view to link to in related links widget.

singular = 'Material'

Singular may be used by templates to display the model name.

ferrosoft.apps.ferrobase.views.media module

class ferrosoft.apps.ferrobase.views.media.CustomFileResponse(*args, as_attachment=False, filename='', **kwargs)[source]

Bases: FileResponse

FileResponse subclass that sets Content-Disposition from an async iterator.

ferrosoft.apps.ferrobase.views.media.FORCE_DOWNLOAD_PARAM = 'dl'

Query parameter (?dl=1) that forces a media file to download as an attachment.

ferrosoft.apps.ferrobase.views.media.restrict_media(request, path)[source]

Authenticated media-serving endpoint with per-file access control.

Looks up the StoredFile for path via StoredFile.get_authenticated_file() (returns None when the current user has no access). The file is streamed asynchronously via servestatic.utils.AsyncFile; ?dl=1 forces a download.

ferrosoft.apps.ferrobase.views.onboarding module

class ferrosoft.apps.ferrobase.views.onboarding.AccountActivationView(*args, **kwargs)[source]

Bases: PlatformActivityMixin, FormView

Final step of self-service onboarding: set a password to activate the account.

activity_title = 'Sign Up'

Activity title should be a very short label e.g. indicating the current model being operated on.

form_class

alias of SignupUserForm

form_valid(form)[source]

Activate the account and redirect to the login page.

get(request, *args, **kwargs)[source]

Validate the token, then dispatch to the base GET handler.

post(request, *args, **kwargs)[source]

Validate the token, then dispatch to the base POST handler.

template_name = 'ferrobase/onboarding/finish_activation.html'
class ferrosoft.apps.ferrobase.views.onboarding.SignupView(*args, **kwargs)[source]

Bases: PlatformActivityMixin, FormView

Public signup form with CAPTCHA gating and background-task dispatch.

SLEEP_TIME = 2

Seconds of artificial delay added to POSTs as a basic rate limiter.

activity_title = 'Sign Up'

Activity title should be a very short label e.g. indicating the current model being operated on.

form_class

alias of SignupForm

form_valid(form)[source]

Enqueue initiate_signup and redirect to the conversion-tracking URL.

When ONBOARDING_CONVERSION_URL is not configured the user is instead returned to the form template with a “request received” banner.

get(request, *args, **kwargs)[source]

Render the form with a fresh CAPTCHA challenge.

get_context_data(**kwargs)[source]

Pass the rendered CAPTCHA image and POST field name to the template.

post(request, *args, **kwargs)[source]

Sleep, verify the CAPTCHA, then process the form (or re-render on failure).

template_name = 'ferrobase/onboarding/signup.html'

ferrosoft.apps.ferrobase.views.organization module

class ferrosoft.apps.ferrobase.views.organization.FeatureAssignmentCreateView(*args, **kwargs)[source]

Bases: DependentCreateView

Create a feature assignment under an existing SubscriptionPlan.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Feature Assignment'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:featureassignment_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

form_class

alias of FeatureAssignmentForm

get_form_kwargs()[source]

Prefill the plan field from the parent object.

model

alias of FeatureAssignment

parent_model

alias of SubscriptionPlan

permission_required = ['ferrobase.add_featureassignment']
class ferrosoft.apps.ferrobase.views.organization.FeatureAssignmentDeleteView(*args, **kwargs)[source]

Bases: DeleteView

Delete a feature assignment; redirects back to its plan.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Feature Assignment'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:featureassignment_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

get_success_url()[source]

Return to the parent plan’s update page.

model

alias of FeatureAssignment

permission_required = ['ferrobase.delete_featureassignment']
class ferrosoft.apps.ferrobase.views.organization.FeatureAssignmentUpdateView(**kwargs)[source]

Bases: UpdateView

Update a feature assignment; redirects back to its plan on success.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Feature Assignment'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:featureassignment_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:featureassignment_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:featureassignment_delete'

Update view displays a button to delete the object if delete_view is not None.

form_class

alias of FeatureAssignmentForm

get_success_url()[source]

Return to the parent plan’s update page.

model

alias of FeatureAssignment

permission_required = ['ferrobase.change_featureassignment']
plural = 'Feature Assignments'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:featureassignment_index'

Name of read view to link to in related links widget.

singular = 'Feature Assignment'

Singular may be used by templates to display the model name.

class ferrosoft.apps.ferrobase.views.organization.FeatureLimiter[source]

Bases: ABC

Get current count of feature to determine whether the limit is reached.

abstractmethod get_count(request)[source]

Return the current count of the limited feature for request.

Return type:

int

class ferrosoft.apps.ferrobase.views.organization.FeatureRequiredMixin[source]

Bases: AccessMixin

Mixin gating a view behind a subscription-plan feature and optional quota.

Anonymous users bypass the check (they fall through to the normal auth flow). Authenticated users must either be on a plan with enable_all_features or hold an explicit FeatureAssignment for feature_required. When a feature_limiter is set, its count is compared against assignment.limit.

dispatch(request, *args, **kwargs)[source]

Enforce the feature/limit policy before dispatching to the view.

feature_limiter: FeatureLimiter | None = None
feature_required: str | None = None
get_feature_required()[source]

Return feature_required or raise ImproperlyConfigured.

handle_no_permission()[source]

Redirect authenticated users to the upgrade page; defer otherwise.

limit_reached(request, assignment)[source]

Return True if the configured limiter’s count meets assignment.limit.

Return type:

bool

validate_feature(request)[source]

Look up the active assignment and plan for the required feature.

Return type:

tuple[FeatureAssignment | None, SubscriptionPlan | None]

class ferrosoft.apps.ferrobase.views.organization.OrganizationCreateView(**kwargs)[source]

Bases: CreateView

Create an organisation.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Organization'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:organization_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

form_class

alias of OrganizationForm

model

alias of Organization

permission_required = ['ferrobase.add_organization']
class ferrosoft.apps.ferrobase.views.organization.OrganizationDeleteView(*args, **kwargs)[source]

Bases: DeleteView

Delete an organisation.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Organization'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:organization_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

model

alias of Organization

permission_required = ['ferrobase.delete_organization']
class ferrosoft.apps.ferrobase.views.organization.OrganizationTableView(**kwargs)[source]

Bases: TableView

Filterable table of organisations.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Organization'

Activity title should be a very short label e.g. indicating the current model being operated on.

create_view: str | Callable[[...], str] | None = 'ferrobase:organization_create'

List view displays a button to create a new object if create_view is not None.

filterset_class

alias of OrganizationFilterSet

model

alias of Organization

ordering = 'name'
permission_required = ['ferrobase.view_organization']
plural = 'Organizations'

Plural may be used by templates to display the model name.

singular = 'Organization'

Singular may be used by templates to display the model name.

table_class

alias of OrganizationTable

class ferrosoft.apps.ferrobase.views.organization.OrganizationUpdateView(**kwargs)[source]

Bases: UpdateView

Update an organisation and display its tenants.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Organization'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:organization_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:organization_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:organization_delete'

Update view displays a button to delete the object if delete_view is not None.

form_class

alias of OrganizationForm

get_context_data(**kwargs)[source]

Add the per-organisation tenant table to the template context.

model

alias of Organization

permission_required = ['ferrobase.change_organization']
plural = 'Organizations'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:organization_index'

Name of read view to link to in related links widget.

Expose a “View Users” link gated on User READ permission.

singular = 'Organization'

Singular may be used by templates to display the model name.

template_name = 'ferrobase/organization/update.html'
class ferrosoft.apps.ferrobase.views.organization.SubscriptionPlanCopyView(*args, **kwargs)[source]

Bases: CopyView

Create a new subscription plan seeded from an existing one’s settings.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Copy Subscription Plan'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:subscriptionplan_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

form_class

alias of SubscriptionPlanForm

model

alias of SubscriptionPlan

permission_required = ['ferrobase.add_subscriptionplan']
static prepare_copy(source, target, **kwargs)[source]

Return preparators that clone every FeatureAssignment of source.

The cloning is deferred via a returned callable so the copy form factory can invoke it after the new plan has been persisted.

class ferrosoft.apps.ferrobase.views.organization.SubscriptionPlanCreateView(**kwargs)[source]

Bases: CreateView

Create a subscription plan.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Subscription Plan'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:subscriptionplan_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

form_class

alias of SubscriptionPlanForm

model

alias of SubscriptionPlan

permission_required = ['ferrobase.add_subscriptionplan']
class ferrosoft.apps.ferrobase.views.organization.SubscriptionPlanDeleteView(*args, **kwargs)[source]

Bases: DeleteView

Delete a subscription plan.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Subscription Plan'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:subscriptionplan_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

model

alias of SubscriptionPlan

permission_required = ['ferrobase.delete_subscriptionplan']
class ferrosoft.apps.ferrobase.views.organization.SubscriptionPlanTableView(**kwargs)[source]

Bases: TableView

Filterable table of subscription plans.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Subscription Plan'

Activity title should be a very short label e.g. indicating the current model being operated on.

create_view: str | Callable[[...], str] | None = 'ferrobase:subscriptionplan_create'

List view displays a button to create a new object if create_view is not None.

filterset_class

alias of SubscriptionPlanFilterSet

model

alias of SubscriptionPlan

ordering = 'name'
permission_required = ['ferrobase.view_subscriptionplan']
plural = 'Subscription Plans'

Plural may be used by templates to display the model name.

singular = 'Subscription Plan'

Singular may be used by templates to display the model name.

table_class

alias of SubscriptionPlanTable

class ferrosoft.apps.ferrobase.views.organization.SubscriptionPlanUpdateView(**kwargs)[source]

Bases: UpdateView

Update a plan and display its associated feature assignments.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Subscription Plan'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:subscriptionplan_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

copy_view: str | Callable[[...], str] | None = 'ferrobase:subscriptionplan_copy'

Update view displays a button to copy the object if copy_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:subscriptionplan_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:subscriptionplan_delete'

Update view displays a button to delete the object if delete_view is not None.

form_class

alias of SubscriptionPlanForm

get_context_data(**kwargs)[source]

Add the per-plan feature-assignment table to the template context.

model

alias of SubscriptionPlan

permission_required = ['ferrobase.change_subscriptionplan']
plural = 'Subscription Plans'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:subscriptionplan_index'

Name of read view to link to in related links widget.

singular = 'Subscription Plan'

Singular may be used by templates to display the model name.

template_name = 'ferrobase/subscriptionplan/update.html'
class ferrosoft.apps.ferrobase.views.organization.UpgradePlanView(**kwargs)[source]

Bases: TemplateView

Static page shown when a feature requires a plan upgrade.

activity_title = 'Upgrade Required'

Activity title should be a very short label e.g. indicating the current model being operated on.

get_context_data(**kwargs)[source]

Expose the marketing plan URL and sales contact from settings.

template_name = 'ferrobase/subscriptionplan/upgrade.html'

ferrosoft.apps.ferrobase.views.partner module

class ferrosoft.apps.ferrobase.views.partner.PartnerCreateView(**kwargs)[source]

Bases: CreateView

Create a business partner using the shared emiflow form.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Business Partner'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:businesspartner_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

form_class

alias of BusinessPartnerForm

form_template = 'ferrobase/businesspartner/form.html'

Template to be included instead of generic form display.

model

alias of BusinessPartner

permission_required = ['ferrobase.add_businesspartner']
class ferrosoft.apps.ferrobase.views.partner.PartnerDeleteView(*args, **kwargs)[source]

Bases: DeleteView

Delete a business partner.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Business Partner'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:businesspartner_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

model

alias of BusinessPartner

permission_required = ['ferrobase.delete_businesspartner']
class ferrosoft.apps.ferrobase.views.partner.PartnerFilterView(**kwargs)[source]

Bases: FilterView

Filterable list of business partners (form and filter live in emiflow).

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Business Partner'

Activity title should be a very short label e.g. indicating the current model being operated on.

create_view: str | Callable[[...], str] | None = 'ferrobase:businesspartner_create'

List view displays a button to create a new object if create_view is not None.

filterset_class

alias of BusinessPartnerFilter

model

alias of BusinessPartner

ordering = 'name'
permission_required = ['ferrobase.view_businesspartner']
plural = 'Business Partners'

Plural may be used by templates to display the model name.

singular = 'Business Partner'

Singular may be used by templates to display the model name.

class ferrosoft.apps.ferrobase.views.partner.PartnerUpdateView(**kwargs)[source]

Bases: UpdateView

Update a business partner using the shared emiflow form.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Business Partner'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:businesspartner_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:businesspartner_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:businesspartner_delete'

Update view displays a button to delete the object if delete_view is not None.

form_class

alias of BusinessPartnerForm

form_template = 'ferrobase/businesspartner/form.html'

Template to be included instead of generic form display.

model

alias of BusinessPartner

permission_required = ['ferrobase.change_businesspartner']
plural = 'Business Partners'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:businesspartner_index'

Name of read view to link to in related links widget.

singular = 'Business Partner'

Singular may be used by templates to display the model name.

ferrosoft.apps.ferrobase.views.password module

ferrosoft.apps.ferrobase.views.password.reset_password(request)[source]

Begin the password-reset flow.

On POST the function always reports sent_mail = True regardless of whether the user exists, which prevents user enumeration through the public form. Mail-sending exceptions are logged but never surfaced to the caller.

ferrosoft.apps.ferrobase.views.password.set_new_password(request, access_key)[source]

Complete the password-reset flow for a token-bearing user.

Validates the token, applies the new password (both confirmation fields must match — enforced by set_password_validated()), persists the user record and deletes the consumed reset request. Redirects to the login page with ?reset=1 on success.

ferrosoft.apps.ferrobase.views.session module

class ferrosoft.apps.ferrobase.views.session.LoginView(**kwargs)[source]

Bases: LoginView

Two-factor login view augmented with the platform’s email footer context.

get_device_context_data(**kwargs)[source]

Add FERROBASE_EMAIL_FOOTER from settings to the device context.

class ferrosoft.apps.ferrobase.views.session.SetupView(**kwargs)[source]

Bases: SetupView

Two-factor setup view augmented with the platform’s email footer context.

get_device_context_data(**kwargs)[source]

Add FERROBASE_EMAIL_FOOTER from settings to the device context.

ferrosoft.apps.ferrobase.views.session.logout_view(request)[source]

Log the user out and render the post-logout confirmation page.

ferrosoft.apps.ferrobase.views.settings module

class ferrosoft.apps.ferrobase.views.settings.IDSequenceCreate(**kwargs)[source]

Bases: CreateView

Create a new ID sequence configuration.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Id Sequence'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:idsequenceconfig_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

form_class

alias of IDSequenceForm

model

alias of IdSequenceConfig

permission_required = ['ferrobase.add_idsequenceconfig']
class ferrosoft.apps.ferrobase.views.settings.IDSequenceRead(**kwargs)[source]

Bases: TableView

Filterable list of ID sequence configurations.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Id Sequence'

Activity title should be a very short label e.g. indicating the current model being operated on.

create_view: str | Callable[[...], str] | None = 'ferrobase:idsequenceconfig_create'

List view displays a button to create a new object if create_view is not None.

filterset_class

alias of IDSequenceFilter

model

alias of IdSequenceConfig

ordering = 'name'
permission_required = ['ferrobase.view_idsequenceconfig']
plural = 'ID Sequences'

Plural may be used by templates to display the model name.

singular = 'ID Sequence'

Singular may be used by templates to display the model name.

table_class

alias of IDSequenceTable

class ferrosoft.apps.ferrobase.views.settings.IDSequenceUpdate(**kwargs)[source]

Bases: UpdateView

Edit an ID sequence; delete is disabled and default related links are hidden.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Id Sequence'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:idsequenceconfig_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:idsequenceconfig_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = None

Update view displays a button to delete the object if delete_view is not None.

form_class

alias of IDSequenceForm

model

alias of IdSequenceConfig

permission_required = ['ferrobase.change_idsequenceconfig']
plural = 'ID Sequences'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:idsequenceconfig_index'

Name of read view to link to in related links widget.

Show default related links, if enabled.

singular = 'ID Sequence'

Singular may be used by templates to display the model name.

class ferrosoft.apps.ferrobase.views.settings.MySettings(**kwargs)[source]

Bases: UpdateView

Self-service “My settings” page for the currently logged-in user.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'My settings'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:user_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:user_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:user_delete'

Update view displays a button to delete the object if delete_view is not None.

form_class

alias of UserSettingsForm

get_object(*args, **kwargs)[source]

Return the authenticated user instead of looking the PK up by URL.

get_success_url()[source]

Stay on the My-settings page after a save.

model

alias of User

permission_required = ['ferrobase.change_user']
plural = 'users'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:user_index'

Name of read view to link to in related links widget.

singular = 'user'

Singular may be used by templates to display the model name.

template_name = 'ferrobase/user/settings.html'
class ferrosoft.apps.ferrobase.views.settings.SettingsIndex(**kwargs)[source]

Bases: TemplateView

Landing page for the settings area, rendering the registered settings menu.

get_context_data(**kwargs)[source]

Expose the per-user/per-tenant settings menu to the template.

template_name = 'ferrobase/settings/index.html'

ferrosoft.apps.ferrobase.views.tenant module

class ferrosoft.apps.ferrobase.views.tenant.TenantCreateView(*args, **kwargs)[source]

Bases: DependentCreateView

Create a tenant scoped to an Organization (the dependent parent).

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Tenant'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view()[source]

Return to the parent organisation, or hide the cancel button.

form_class

alias of TenantForm

get_form_kwargs()[source]

Enable add-tenant mode and prefill organization from the parent.

model

alias of Tenant

parent_model

alias of Organization

permission_required = ['ferrobase.add_tenant']
template_name = 'ferrobase/tenant/create.html'
class ferrosoft.apps.ferrobase.views.tenant.TenantDeleteView(*args, **kwargs)[source]

Bases: DeleteView

Delete a tenant; redirects back to the owning organisation.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Tenant'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:tenant_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

get_success_url()[source]

Return to the owning organisation’s update page after deletion.

model

alias of Tenant

permission_required = ['ferrobase.delete_tenant']
class ferrosoft.apps.ferrobase.views.tenant.TenantUpdateView(**kwargs)[source]

Bases: UpdateView

Update a tenant; navigation always returns to the parent organisation.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'Tenant'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view()[source]

Cancel returns to the owning organisation’s update page.

create_view: str | Callable[[...], str] | None = 'ferrobase:tenant_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:tenant_delete'

Update view displays a button to delete the object if delete_view is not None.

form_class

alias of TenantForm

get_success_url()[source]

Success also returns to the owning organisation’s update page.

model

alias of Tenant

permission_required = ['ferrobase.change_tenant']
plural = 'Tenants'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:tenant_index'

Name of read view to link to in related links widget.

Show default related links, if enabled.

singular = 'Tenant'

Singular may be used by templates to display the model name.

ferrosoft.apps.ferrobase.views.tenant.choose_tenant(request)[source]

Tenant-selection page; auto-redirects when the user has a single tenant.

ferrosoft.apps.ferrobase.views.user module

class ferrosoft.apps.ferrobase.views.user.UserCreateView(**kwargs)[source]

Bases: FeatureRequiredMixin, CreateView

Create a user; the “users” feature limit enforces subscription caps.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'User'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:user_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

feature_limiter: FeatureLimiter | None = <ferrosoft.apps.ferrobase.views.user.UserLimiter object>
feature_required: str | None = 'users'
form_class

alias of UserCreationForm

get_form_kwargs()[source]

Inject the organisation and the superuser-only org-selection flag.

model

alias of User

permission_required = ['ferrobase.add_user']
template_name = 'ferrobase/user/detail.html'
class ferrosoft.apps.ferrobase.views.user.UserDeleteView(*args, **kwargs)[source]

Bases: FeatureRequiredMixin, DeleteView

Delete a user; both GET and POST enforce same-organisation authorisation.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'User'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:user_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

feature_required: str | None = 'users'
get(request, *args, **kwargs)[source]

Authorise then defer to the base GET handler.

model

alias of User

permission_required = ['ferrobase.delete_user']
post(request, *args, **kwargs)[source]

Authorise then defer to the base POST handler.

class ferrosoft.apps.ferrobase.views.user.UserGroupsView(**kwargs)[source]

Bases: FeatureRequiredMixin, UpdateView

Assign auth groups to a user via UserGroupsForm.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'User groups'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:user_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:user_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:user_delete'

Update view displays a button to delete the object if delete_view is not None.

feature_required: str | None = 'users'
form_class

alias of UserGroupsForm

model

alias of User

permission_required = ['ferrobase.change_user']
plural = 'users'

Plural may be used by templates to display the model name.

read_view: str | Callable[[...], str] | None = 'ferrobase:user_index'

Name of read view to link to in related links widget.

singular = 'user'

Singular may be used by templates to display the model name.

class ferrosoft.apps.ferrobase.views.user.UserLimiter[source]

Bases: FeatureLimiter

Counts users in the request user’s organisation for plan-limit checks.

get_count(request)[source]

Return the current user count for the organisation (excluding tenants).

Return type:

int

class ferrosoft.apps.ferrobase.views.user.UserList(**kwargs)[source]

Bases: FeatureRequiredMixin, TableView

List users, scoped to the current organisation for non-superusers.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'User'

Activity title should be a very short label e.g. indicating the current model being operated on.

create_view: str | Callable[[...], str] | None = 'ferrobase:user_create'

List view displays a button to create a new object if create_view is not None.

feature_required: str | None = 'users'
filterset_class

alias of UserFilterSet

get_queryset()[source]

Restrict to the request user’s organisation unless they are a superuser.

model

alias of User

ordering = 'username'
permission_required = ['ferrobase.view_user']
plural = 'users'

Plural may be used by templates to display the model name.

singular = 'user'

Singular may be used by templates to display the model name.

table_class

alias of UserTable

class ferrosoft.apps.ferrobase.views.user.UserUpdateView(**kwargs)[source]

Bases: FeatureRequiredMixin, UpdateView

Update a user; both GET and POST enforce same-organisation authorisation.

activity_app = 'ferrobase'

Django identifier of the app the activity belongs to. If it is None, the app is derived from template_name.

activity_title = 'User'

Activity title should be a very short label e.g. indicating the current model being operated on.

cancel_view: str | Callable[[...], str] | None = 'ferrobase:user_index'

Create, Update and Delete views display a button to cancel the operation if cancel_view is not None.

create_view: str | Callable[[...], str] | None = 'ferrobase:user_create'

List view displays a button to create a new object if create_view is not None.

delete_view: str | Callable[[...], str] | None = 'ferrobase:user_delete'

Update view displays a button to delete the object if delete_view is not None.

feature_required: str | None = 'users'
form_class

alias of UserUpdateForm

get(request, *args, **kwargs)[source]

Authorise then defer to the base GET handler.

model

alias of User

permission_required = ['ferrobase.change_user']
plural = 'users'

Plural may be used by templates to display the model name.

post(request, *args, **kwargs)[source]

Authorise then defer to the base POST handler.

read_view: str | Callable[[...], str] | None = 'ferrobase:user_index'

Name of read view to link to in related links widget.

singular = 'user'

Singular may be used by templates to display the model name.

template_name = 'ferrobase/user/detail.html'
ferrosoft.apps.ferrobase.views.user.assign_user_resources(request, pk)[source]

Edit the storage-location grants assigned to a user.

Renders the assignment form on GET. On POST the submitted location UUIDs are validated via UserResourcesForm and propagated through CompanySite.set_locations_for_user(); both the user and the associated LocalUser are refreshed from the database afterward.