HasWorkflowModelMixin
Overview
Model-level utility methods for objects with workflow.
Meta
Source
server/vueda/workflow/models.py:601
_state_permission_rules
Every state rule that applies to this object for groups, keyed by permission codename.
One query resolves every codename the current state grants or denies. has_perm asks about one permission at a time, so a pass evaluating several against one object would otherwise pay a round trip for each.
A codename absent from the mapping has no matching rule, which is the None that check_state_permission returns.
The cache is keyed by caller rather than by the group set, so groups stays a subquery on the rule lookup and never becomes a query of its own. Each new block resolves again, so a caller whose group membership changed is read afresh on its next authorization pass even when the same user instance is reused.
Signature
_state_permission_rules(self, groups, caller)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| groups | collections.abc.Iterable[str] | collections.abc.Iterable[int] | django.db.models.query.QuerySet | yes | |
| caller | django.db.models.base.Model | None | yes |
Returns
dict[str, bool]
Source
server/vueda/workflow/models.py:823
allow_transition
Check if transition is allowed for this object. return falsy or a string will raise a InvalidTransitionError exception in apply_transition
Resolves only transition. The cost does not grow with the number of other transitions leaving the current state. Use available_transitions when the permitted set itself is what is wanted.
Signature
allow_transition(self, transition, user)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| transition | <class 'vueda.workflow.models.Transition'> | yes | |
| user | doc_app.models.User | None | yes |
Returns
bool | str
Source
server/vueda/workflow/models.py:887
apply_checked_transition
Write an already-authorized transition (as returned by check_transition) without re-checking permissions or availability.
Returns the target state and the object state's new revision, which is None when the object has no state row to record.
Signature
apply_checked_transition(self, transition, user, dry_run)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| transition | <class 'vueda.workflow.models.Transition'> | yes | |
| user | doc_app.models.User | None | yes | |
| dry_run | <class 'bool'> | yes |
Returns
tuple[vueda.workflow.models.State, str | None]
Source
server/vueda/workflow/models.py:987
apply_transition
Apply a transition to the object.
Signature
apply_transition(self, transition_code, user, dry_run)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| transition_code | <class 'str'> | yes | |
| user | doc_app.models.User | None | yes | |
| dry_run | <class 'bool'> | yes |
Returns
tuple[vueda.workflow.models.State, str | None]
Source
server/vueda/workflow/models.py:1001
available_transitions
Returns available transitions for this object.
The whole pass runs inside one cached_workflow_state() block, so the object's workflow, current state, and state rules are read once rather than once per candidate transition.
Signature
available_transitions(self, user)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| user | doc_app.models.User | None | yes |
Returns
<class 'django.db.models.query.QuerySet'>
Source
server/vueda/workflow/models.py:694
available_transitions_for
Returns available transitions for a list of objects.
A transition is available when at least one of objs sits in one of its source states and user may take it on that object. This matches the source-state filter, which admits a transition leaving any of the objects' states rather than all of them.
check_transition_permission resolves user.has_perms(perms, obj=...), so the answer depends on the object it receives. This classmethod therefore loads the concrete instances and asks each candidate object rather than asking the model class.
Signature
available_transitions_for(cls, objs, user)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| cls | yes | ||
| objs | list[vueda.workflow.models.HasWorkflowModelMixin] | list[int] | django.db.models.query.QuerySet | yes | |
| user | doc_app.models.User | None | yes |
Returns
<class 'django.db.models.query.QuerySet'>
Source
server/vueda/workflow/models.py:727
cached_workflow_state
Hold this object's workflow and object_state for the duration of the block.
One authorization pass reads both repeatedly: check_state_permission resolves the current state for every permission it is asked about, and VuedaUserMixin.has_perm reads the workflow to decide whether state rules apply at all. Without this, each read is a fresh query.
The cache is scoped to a block rather than to the instance on purpose. execute_transition checks a transition, takes a row lock, and checks again against the locked row, and that second check has to observe any state written in between. Nested blocks reuse the outermost cache and leave it to the outermost block to clear.
Signature
cached_workflow_state(self)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes |
Returns
collections.abc.Iterator[None]
Source
server/vueda/workflow/models.py:641
check_state_permission
Check whether the object's current state grants or denies perm for any of groups. Returns True (grant), False (deny), or None (no state rule applies). When multiple rules match, deny takes precedence over grant.
caller is the user groups belongs to. Passing it lets one cached_workflow_state() block resolve that caller's rules once instead of once per permission. Without it every call resolves, which is what an uncached caller gets.
Signature
check_state_permission(self, perm, groups, caller)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| perm | <class 'str'> | yes | |
| groups | collections.abc.Iterable[str] | collections.abc.Iterable[int] | django.db.models.query.QuerySet | yes | |
| caller | django.db.models.base.Model | None | yes |
Returns
bool | None
Source
server/vueda/workflow/models.py:806
check_transition
Validate that transition_code can be applied by user, without writing anything.
Performs the same permission and allow_transition checks as apply_transition (raising the same exceptions), and resolves the effective user (falling back to the acting user the history middleware records on the action, then the system user, exactly as apply_transition does). Callers that need to gate a transition on warnings (see get_transition_warnings) before writing should call this first, then apply_checked_transition.
Signature
check_transition(self, transition_code, user)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| transition_code | <class 'str'> | yes | |
| user | doc_app.models.User | None | yes |
Returns
tuple[vueda.workflow.models.Transition, doc_app.models.User]
Source
server/vueda/workflow/models.py:951
check_transition_permission
user as None means superuser, pass django's AnonymousUser if you want to check for anonymous user.
Signature
check_transition_permission(self, transition, user)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| transition | <class 'vueda.workflow.models.Transition'> | yes | |
| user | doc_app.models.User | None | yes |
Returns
<class 'bool'>
Source
server/vueda/workflow/models.py:868
check_workflow_permission
Whether user holds the workflow's configured permissions.
user as None means programmatic use; pass Django's AnonymousUser to check an anonymous request. obj scopes the check to one object, so an object permission backend decides the configured workflow permissions the way it decides the target model's own.
A state rule is not a substitute for a configured workflow permission. State rules apply where a concrete object supplies the state, which is the object permission decision this check passes obj to, not a reason to skip the check.
Signature
check_workflow_permission(cls, user, obj)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| cls | yes | ||
| user | doc_app.models.User | None | yes | |
| obj | django.db.models.base.Model | None | yes |
Returns
<class 'bool'>
Source
server/vueda/workflow/models.py:778
create_object_state
Create a workflow object for this object.
Signature
create_object_state(self)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes |
Source
server/vueda/workflow/models.py:623
fast_available_transitions
Returns available transitions for this object without permission checks.
Signature
fast_available_transitions(self)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes |
Returns
<class 'django.db.models.query.QuerySet'>
Source
server/vueda/workflow/models.py:712
fast_transition
Apply a transition without permission checks. Raises InvalidTransitionError if the transition is not available from the current state, unless the TransitionSource is marked ignored, in which case on_transition_ignored is called.
Signature
fast_transition(self, transition_code)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| transition_code | <class 'str'> | yes |
Source
server/vueda/workflow/models.py:1010
get_content_type
Return the ContentType for this model class. Result is cached by Django.
Signature
get_content_type(cls)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| cls | yes |
Returns
<class 'django.contrib.contenttypes.models.ContentType'>
Source
server/vueda/workflow/models.py:635
get_transition
Return the Transition with the given code in this object's workflow. Raises Transition.DoesNotExist if not found.
Signature
get_transition(self, transition_code)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| transition_code | <class 'str'> | yes |
Returns
<class 'vueda.workflow.models.Transition'>
Source
server/vueda/workflow/models.py:929
get_transition_warnings
Hook returning advisory warnings for a transition, consulted before it is written.
Override to report warnings that should gate the transition behind confirmation (HTTP 409) without denying it outright the way allow_transition does. Return the aggregate {field: [messages]} warnings dict (use "non_field_errors" for warnings not tied to a field). The default returns {}, meaning no confirmation is required. See vueda.core.exceptions.gate_warnings for how the caller turns this into a 409.
Signature
get_transition_warnings(self, transition, user)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| transition | <class 'vueda.workflow.models.Transition'> | yes | |
| user | doc_app.models.User | None | yes |
Returns
<class 'dict'>
Source
server/vueda/workflow/models.py:917
on_transition
Override this method to add custom logic on transition.
Signature
on_transition(self, transition, user, dry_run)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| transition | <class 'vueda.workflow.models.Transition'> | yes | |
| user | doc_app.models.User | None | yes | |
| dry_run | <class 'bool'> | yes |
Source
server/vueda/workflow/models.py:1039
on_transition_ignored
Override this method to add custom logic when a transition is intentionally ignored.
Signature
on_transition_ignored(self, transition, user)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| transition | <class 'vueda.workflow.models.Transition'> | yes | |
| user | doc_app.models.User | None | yes |
Source
server/vueda/workflow/models.py:1044
save
Save the object and create a workflow object if it doesn't exist.
Signature
save(self, args, kwargs)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| args | yes | ||
| kwargs | yes |
Source
server/vueda/workflow/models.py:615
should_ignore_transition_from_state
Return True if the transition should be treated as a no-op from the current state.
Signature
should_ignore_transition_from_state(self, transition)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| transition | <class 'vueda.workflow.models.Transition'> | yes |
Returns
<class 'bool'>
Source
server/vueda/workflow/models.py:941
update_object_state
Sets the history user to the system user if a user isn't passed in.
Signature
update_object_state(self, state, user, change_reason)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| self | yes | ||
| state | yes | ||
| user | yes | ||
| change_reason | yes |
Source
server/vueda/workflow/models.py:1028
_meta
_workflow_state_cache
object_state
Return the ObjectState record for this instance, or None if not yet created.
Source
server/vueda/workflow/models.py:676
object_states_proxy
Accessor to the related objects manager on the one-to-many relation created by GenericRelation.
In the example::
class Post(Model):
comments = GenericRelation(Comment)
post.comments is a ReverseGenericManyToOneDescriptor instance.
workflow
Return the Workflow configured for this model, or None if none exists.
Source
server/vueda/workflow/models.py:665
workflow_state
Return the current State for this instance, or None if no state exists.
Source
server/vueda/workflow/models.py:688
Source
server/vueda/workflow/models.py:588