---
url: "https://vueda.dev/v3/reference/api/py/vueda.workflow.management.commands.makeworkflowmigrations.md"
title: "commands.makeworkflowmigrations"
---

# commands.makeworkflowmigrations

## Overview

Management command for generating workflow state and transition migrations from change history.

## Classes

- [Command](/v3/reference/api/py/vueda.workflow.management.commands.makeworkflowmigrations/Command.md)
- [RecordChange](/v3/reference/api/py/vueda.workflow.management.commands.makeworkflowmigrations/RecordChange.md)
- [RecordDelta](/v3/reference/api/py/vueda.workflow.management.commands.makeworkflowmigrations/RecordDelta.md)
- [WorkflowChangeTypes](/v3/reference/api/py/vueda.workflow.management.commands.makeworkflowmigrations/WorkflowChangeTypes.md)

## `apply_and_save_changes` {#apply_and_save_changes}

Set each changed field in ``data`` on ``obj``, then save ``obj``.

A changed field holds an ``(old, new)`` tuple, and ``reversing`` applies the old value. Fields that are
not tuples are skipped. Generated workflow migrations copy this function.

### Signature {#apply_and_save_changes-signature}

`apply_and_save_changes(obj, data, reversing)`

#### Parameters {#apply_and_save_changes-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="apply_and_save_changes-param-obj">obj</span> |  | yes |  |  |
| <span id="apply_and_save_changes-param-data">data</span> |  | yes |  |  |
| <span id="apply_and_save_changes-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#apply_and_save_changes-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:1191`

## `backwards_migrate_workflow` {#backwards_migrate_workflow}

Undo a generated workflow migration's ``changed_items`` in reverse order.

Adds become deletes, deletes become adds, and changed fields get their old values back. Object
states change only for the workflows ``changed_items`` names: a removed workflow's object states
are deleted, an object in a removed state is restored from its history or reset to the initial
state, and a re-created workflow gives its objects the initial state. Every other object state
keeps its row and its state. Generated workflow migrations call this from their reverse step; the
migrations import it when made with ``--import-instead`` and copy it otherwise.

### Signature {#backwards_migrate_workflow-signature}

`backwards_migrate_workflow(apps, changed_items, change_reason)`

#### Parameters {#backwards_migrate_workflow-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="backwards_migrate_workflow-param-apps">apps</span> |  | yes |  |  |
| <span id="backwards_migrate_workflow-param-changed_items">changed_items</span> |  | yes |  |  |
| <span id="backwards_migrate_workflow-param-change_reason">change_reason</span> |  | yes |  |  |

### Source {#backwards_migrate_workflow-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:227`

## `compare_records` {#compare_records}

Return the fields whose value differs between two events.

### Signature {#compare_records-signature}

`compare_records(old_record, new_record)`

#### Parameters {#compare_records-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="compare_records-param-old_record">old_record</span> |  | yes |  |  |
| <span id="compare_records-param-new_record">new_record</span> |  | yes |  |  |

### Source {#compare_records-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:1162`

## `delete_object_states_of_removed_workflows` {#delete_object_states_of_removed_workflows}

Delete the object states of each workflow the reversal of ``changed_items`` removes.

A workflow the migration added has no state left to give its objects once the reversal removes
it, and its object states protect it from deletion. Returns the record of released object states
that ``release_state_objects`` and ``settle_released_object_states`` add to. Generated workflow
migrations copy this function and reach it through ``backwards_migrate_workflow``.

### Signature {#delete_object_states_of_removed_workflows-signature}

`delete_object_states_of_removed_workflows(apps, changed_items)`

#### Parameters {#delete_object_states_of_removed_workflows-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="delete_object_states_of_removed_workflows-param-apps">apps</span> |  | yes |  |  |
| <span id="delete_object_states_of_removed_workflows-param-changed_items">changed_items</span> |  | yes |  |  |

### Source {#delete_object_states_of_removed_workflows-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:890`

## `forwards_migrate_workflow` {#forwards_migrate_workflow}

Apply a generated workflow migration's ``changed_items`` in order, then sync workflow object states.

Generated workflow migrations call this from their forwards step; the migrations import it when
made with ``--import-instead`` and copy it otherwise. All writes are grouped under one migration
action named by ``change_reason``.

### Signature {#forwards_migrate_workflow-signature}

`forwards_migrate_workflow(apps, changed_items, change_reason)`

#### Parameters {#forwards_migrate_workflow-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="forwards_migrate_workflow-param-apps">apps</span> |  | yes |  |  |
| <span id="forwards_migrate_workflow-param-changed_items">changed_items</span> |  | yes |  |  |
| <span id="forwards_migrate_workflow-param-change_reason">change_reason</span> |  | yes |  |  |

### Source {#forwards_migrate_workflow-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:180`

## `get_attr_names_for_workflow_models` {#get_attr_names_for_workflow_models}

Map each workflow model name to a mapping of its field names to their attribute names (``attname``).

The command adds fields renamed by migrations to this, then reads recorded field names through it.

### Signature {#get_attr_names_for_workflow_models-signature}

`get_attr_names_for_workflow_models()`

### Source {#get_attr_names_for_workflow_models-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:1096`

## `get_history_diff` {#get_history_diff}

Classify one write and return what it changed.

A write with nothing before it is an add, and one whose event records a delete is a delete. Each
compares against an empty row of the same model, so every field the write set or cleared shows
up as a change.

### Signature {#get_history_diff-signature}

`get_history_diff(old_history_record, new_history_record)`

#### Parameters {#get_history_diff-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="get_history_diff-param-old_history_record">old_history_record</span> |  | yes |  |  |
| <span id="get_history_diff-param-new_history_record">new_history_record</span> |  | yes |  |  |

### Source {#get_history_diff-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:1172`

## `get_id_values_from_dict` {#get_id_values_from_dict}

Return ``id_data`` with each value passed through ``get_id_values_from_item``.

The result finds the row as it stands now. Generated workflow migrations copy this function.

### Signature {#get_id_values_from_dict-signature}

`get_id_values_from_dict(id_data, reversing)`

#### Parameters {#get_id_values_from_dict-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="get_id_values_from_dict-param-id_data">id_data</span> |  | yes |  |  |
| <span id="get_id_values_from_dict-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#get_id_values_from_dict-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:1065`

## `get_id_values_from_item` {#get_id_values_from_item}

Return the value that finds a row as it stands now: the old side of an ``(old, new)`` tuple.

``reversing`` picks the new side instead. A value that is not a tuple is returned unchanged.
Generated workflow migrations copy this function.

### Signature {#get_id_values_from_item-signature}

`get_id_values_from_item(values, reversing)`

#### Parameters {#get_id_values_from_item-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="get_id_values_from_item-param-values">values</span> |  | yes |  |  |
| <span id="get_id_values_from_item-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#get_id_values_from_item-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:1050`

## `get_migration_imports` {#get_migration_imports}

Return the full, ordered set of import lines a workflow migration file's import section is replaced with.

``direct_runpython_import`` adds a direct ``from django.db.migrations import RunPython`` import, needed
when the class Migration block being preserved calls ``RunPython(...)`` directly instead of
``migrations.RunPython(...)``.

When ``as_mapping`` is True, an ordered mapping is returned instead: keys are single-name tuples (an
import only ever binds one name, per this project's force-single-line isort convention) and values are
the current import line, each ending in its own newline and prefixed with a blank line where it opens
a new isort group. This is used by ``updateworkflowmigrations`` to update or insert only the imports
it recognizes in an existing migration, leaving any hand-added imports (or comments) around them
untouched.

### Signature {#get_migration_imports-signature}

`get_migration_imports(import_instead, direct_runpython_import, as_mapping)`

#### Parameters {#get_migration_imports-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="get_migration_imports-param-import_instead">import_instead</span> |  | no | `False` |  |
| <span id="get_migration_imports-param-direct_runpython_import">direct_runpython_import</span> |  | no | `False` |  |
| <span id="get_migration_imports-param-as_mapping">as_mapping</span> |  | no | `False` |  |

### Source {#get_migration_imports-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:1215`

## `get_migration_sources` {#get_migration_sources}

Return the source-code strings that follow changed_data in a workflow migration file.

When ``as_mapping`` is True, an ordered mapping is returned instead: keys are tuples of every name
(old and current) that identifies a given function/class across versions of this command, and values
are the current source for it. This is used by ``updateworkflowmigrations`` to replace only the
functions it recognizes in an existing migration, leaving any hand-added code around them untouched.

### Signature {#get_migration_sources-signature}

`get_migration_sources(import_instead, as_mapping)`

#### Parameters {#get_migration_sources-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="get_migration_sources-param-import_instead">import_instead</span> |  | no | `False` |  |
| <span id="get_migration_sources-param-as_mapping">as_mapping</span> |  | no | `False` |  |

### Source {#get_migration_sources-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:1277`

## `handle_initial_state` {#handle_initial_state}

Add, change, or delete a workflow's initial state to match ``changed_item``.

The function finds related rows by the identifying fields stored in ``changed_item``. ``reversing`` restores
old values on a change. Generated workflow migrations copy this function and reach it through
``forwards_migrate_workflow`` and ``backwards_migrate_workflow``.

### Signature {#handle_initial_state-signature}

`handle_initial_state(apps, changed_item, change_reason, reversing)`

#### Parameters {#handle_initial_state-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="handle_initial_state-param-apps">apps</span> |  | yes |  |  |
| <span id="handle_initial_state-param-changed_item">changed_item</span> |  | yes |  |  |
| <span id="handle_initial_state-param-change_reason">change_reason</span> |  | yes |  |  |
| <span id="handle_initial_state-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#handle_initial_state-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:534`

## `handle_state` {#handle_state}

Add, change, or delete one workflow state to match ``changed_item``.

The function finds related rows by the identifying fields stored in ``changed_item``. ``reversing`` restores
old values on a change. Generated workflow migrations copy this function and reach it through
``forwards_migrate_workflow`` and ``backwards_migrate_workflow``.

### Signature {#handle_state-signature}

`handle_state(apps, changed_item, change_reason, reversing)`

#### Parameters {#handle_state-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="handle_state-param-apps">apps</span> |  | yes |  |  |
| <span id="handle_state-param-changed_item">changed_item</span> |  | yes |  |  |
| <span id="handle_state-param-change_reason">change_reason</span> |  | yes |  |  |
| <span id="handle_state-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#handle_state-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:414`

## `handle_state_objects` {#handle_state_objects}

Run ``manage_state_objects`` for every workflow, using the migration's own models.

``reversing`` deletes all object states instead. Generated workflow migrations copy this function
and reach it through ``forwards_migrate_workflow`` and ``backwards_migrate_workflow``.

### Signature {#handle_state_objects-signature}

`handle_state_objects(apps, reversing)`

#### Parameters {#handle_state_objects-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="handle_state_objects-param-apps">apps</span> |  | yes |  |  |
| <span id="handle_state_objects-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#handle_state_objects-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:860`

## `handle_state_permission` {#handle_state_permission}

Add, change, or delete one state permission (a group's permission in a state) to match ``changed_item``.

The function finds related rows by the identifying fields stored in ``changed_item``. ``reversing`` restores
old values on a change. Generated workflow migrations copy this function and reach it through
``forwards_migrate_workflow`` and ``backwards_migrate_workflow``.

### Signature {#handle_state_permission-signature}

`handle_state_permission(apps, changed_item, change_reason, reversing)`

#### Parameters {#handle_state_permission-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="handle_state_permission-param-apps">apps</span> |  | yes |  |  |
| <span id="handle_state_permission-param-changed_item">changed_item</span> |  | yes |  |  |
| <span id="handle_state_permission-param-change_reason">change_reason</span> |  | yes |  |  |
| <span id="handle_state_permission-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#handle_state_permission-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:453`

## `handle_transition` {#handle_transition}

Add, change, or delete one transition to match ``changed_item``.

The function finds related rows by the identifying fields stored in ``changed_item``. ``reversing`` restores
old values on a change. Generated workflow migrations copy this function and reach it through
``forwards_migrate_workflow`` and ``backwards_migrate_workflow``.

### Signature {#handle_transition-signature}

`handle_transition(apps, changed_item, change_reason, reversing)`

#### Parameters {#handle_transition-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="handle_transition-param-apps">apps</span> |  | yes |  |  |
| <span id="handle_transition-param-changed_item">changed_item</span> |  | yes |  |  |
| <span id="handle_transition-param-change_reason">change_reason</span> |  | yes |  |  |
| <span id="handle_transition-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#handle_transition-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:597`

## `handle_transition_permission` {#handle_transition_permission}

Add, change, or delete one transition permission to match ``changed_item``.

The function finds related rows by the identifying fields stored in ``changed_item``. ``reversing`` restores
old values on a change. Generated workflow migrations copy this function and reach it through
``forwards_migrate_workflow`` and ``backwards_migrate_workflow``.

### Signature {#handle_transition_permission-signature}

`handle_transition_permission(apps, changed_item, change_reason, reversing)`

#### Parameters {#handle_transition_permission-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="handle_transition_permission-param-apps">apps</span> |  | yes |  |  |
| <span id="handle_transition_permission-param-changed_item">changed_item</span> |  | yes |  |  |
| <span id="handle_transition_permission-param-change_reason">change_reason</span> |  | yes |  |  |
| <span id="handle_transition_permission-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#handle_transition_permission-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:653`

## `handle_transition_source` {#handle_transition_source}

Add, change, or delete one transition source state to match ``changed_item``.

The function finds related rows by the identifying fields stored in ``changed_item``. ``reversing`` restores
old values on a change. Generated workflow migrations copy this function and reach it through
``forwards_migrate_workflow`` and ``backwards_migrate_workflow``.

### Signature {#handle_transition_source-signature}

`handle_transition_source(apps, changed_item, change_reason, reversing)`

#### Parameters {#handle_transition_source-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="handle_transition_source-param-apps">apps</span> |  | yes |  |  |
| <span id="handle_transition_source-param-changed_item">changed_item</span> |  | yes |  |  |
| <span id="handle_transition_source-param-change_reason">change_reason</span> |  | yes |  |  |
| <span id="handle_transition_source-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#handle_transition_source-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:732`

## `handle_workflow` {#handle_workflow}

Add, change, or delete one workflow to match ``changed_item``.

The function finds related rows by the identifying fields stored in ``changed_item``. ``reversing`` restores
old values on a change. Generated workflow migrations copy this function and reach it through
``forwards_migrate_workflow`` and ``backwards_migrate_workflow``.

### Signature {#handle_workflow-signature}

`handle_workflow(apps, changed_item, change_reason, reversing)`

#### Parameters {#handle_workflow-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="handle_workflow-param-apps">apps</span> |  | yes |  |  |
| <span id="handle_workflow-param-changed_item">changed_item</span> |  | yes |  |  |
| <span id="handle_workflow-param-change_reason">change_reason</span> |  | yes |  |  |
| <span id="handle_workflow-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#handle_workflow-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:320`

## `handle_workflow_permission` {#handle_workflow_permission}

Add, change, or delete one workflow permission to match ``changed_item``.

The function finds related rows by the identifying fields stored in ``changed_item``. ``reversing`` restores
old values on a change. Generated workflow migrations copy this function and reach it through
``forwards_migrate_workflow`` and ``backwards_migrate_workflow``.

### Signature {#handle_workflow_permission-signature}

`handle_workflow_permission(apps, changed_item, change_reason, reversing)`

#### Parameters {#handle_workflow_permission-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="handle_workflow_permission-param-apps">apps</span> |  | yes |  |  |
| <span id="handle_workflow_permission-param-changed_item">changed_item</span> |  | yes |  |  |
| <span id="handle_workflow_permission-param-change_reason">change_reason</span> |  | yes |  |  |
| <span id="handle_workflow_permission-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#handle_workflow_permission-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:354`

## `make_sure_permissions_exist` {#make_sure_permissions_exist}

Create any missing permissions for the app named ``app_label``.

Generated workflow migrations run this before applying their changes, so the permissions those changes
name exist. The migrations import it when made with ``--import-instead`` and copy it otherwise.

### Signature {#make_sure_permissions_exist-signature}

`make_sure_permissions_exist(app_label)`

#### Parameters {#make_sure_permissions_exist-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="make_sure_permissions_exist-param-app_label">app_label</span> |  | yes |  |  |

### Source {#make_sure_permissions_exist-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:1077`

## `manage_state_objects` {#manage_state_objects}

Create missing object states and move states with only a recorded creation to the initial state.

An object state with only its creation recorded against it is still wherever it was put, so a
changed initial state moves it. One that carries any later event was moved by someone, and the
state they moved it to is theirs to keep. A state with no events also stays where it is: it may
predate the event triggers, so missing history does not prove that it has never moved.

TODO: An earlier run of this counts as someone, because its update is an event like any other.
  A workflow whose initial state changes twice therefore moves its objects only the first time.
  Telling the two apart needs the sync's own writes to be identifiable, which the action context
  cannot currently do here: pghistory sets its context as a transaction-local, so an action
  opened around these writes is still attributed to everything else written in the same
  transaction.

### Signature {#manage_state_objects-signature}

`manage_state_objects(workflow, obj_class, workflow_obj_state_class, object_state_event_class, reversing)`

#### Parameters {#manage_state_objects-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="manage_state_objects-param-workflow">workflow</span> |  | yes |  |  |
| <span id="manage_state_objects-param-obj_class">obj_class</span> |  | yes |  |  |
| <span id="manage_state_objects-param-workflow_obj_state_class">workflow_obj_state_class</span> |  | yes |  |  |
| <span id="manage_state_objects-param-object_state_event_class">object_state_event_class</span> |  | yes |  |  |
| <span id="manage_state_objects-param-reversing">reversing</span> |  | no | `False` |  |

### Source {#manage_state_objects-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:816`

## `rebuild_migration_apps` {#rebuild_migration_apps}

Return a fresh registry of the models in ``apps``, in which every relation points at a model of its own.

Some migration operations, such as ``AlterModelOptions`` and pgtrigger's ``AddTrigger``, reload a
model with ``delay=True``. That re-renders the model and its direct relations but not the models
that point at them, so a foreign key can keep an older class than ``apps.get_model()`` returns,
and filtering through it raises ``ValueError``. Django re-renders the registry before a forwards
``RunPython`` but not before a backwards one (https://code.djangoproject.com/ticket/33586), so
the reverse step rebuilds it. Generated workflow migrations copy this function and reach it
through ``backwards_migrate_workflow``.

VUEDA keeps it until the oldest Django version it supports includes the fix. A copy in a
migration can stay after that, because rebuilding a registry that is already consistent changes
nothing.

### Signature {#rebuild_migration_apps-signature}

`rebuild_migration_apps(apps)`

#### Parameters {#rebuild_migration_apps-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="rebuild_migration_apps-param-apps">apps</span> |  | yes |  |  |

### Source {#rebuild_migration_apps-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:242`

## `release_state_objects` {#release_state_objects}

Move every object out of the state that ``changed_item`` is about to delete.

Each object returns to the most recent state in its history that its workflow still has. An
object with no such state moves to the workflow's initial state, or loses its object state when
the workflow has none. Rows are updated in place, so each keeps its id and its history.
``released`` records each move for ``settle_released_object_states``. Generated workflow
migrations copy this function and reach it through ``backwards_migrate_workflow``.

### Signature {#release_state_objects-signature}

`release_state_objects(apps, changed_item, released)`

#### Parameters {#release_state_objects-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="release_state_objects-param-apps">apps</span> |  | yes |  |  |
| <span id="release_state_objects-param-changed_item">changed_item</span> |  | yes |  |  |
| <span id="release_state_objects-param-released">released</span> |  | yes |  |  |

### Source {#release_state_objects-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:924`

## `settle_released_object_states` {#settle_released_object_states}

Finish the object state changes of a reversal, then report them.

An object reset to the initial state moves to the initial state the workflow has once the whole
reversal has run, which a later step may have changed. An object left without a state, and every
object of a re-created workflow, gets that initial state. Generated workflow migrations copy this
function and reach it through ``backwards_migrate_workflow``.

### Signature {#settle_released_object_states-signature}

`settle_released_object_states(apps, released, recreated_workflow_ids)`

#### Parameters {#settle_released_object_states-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="settle_released_object_states-param-apps">apps</span> |  | yes |  |  |
| <span id="settle_released_object_states-param-released">released</span> |  | yes |  |  |
| <span id="settle_released_object_states-param-recreated_workflow_ids">recreated_workflow_ids</span> |  | yes |  |  |

### Source {#settle_released_object_states-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:978`

## `tracked_field_names` {#tracked_field_names}

Return an event model's tracked columns as ``(name, attname)`` pairs.

pghistory copies the tracked row's concrete fields and adds its own ``pgh_`` columns. Change data
is keyed by field name and read by attname, so both are needed.

### Signature {#tracked_field_names-signature}

`tracked_field_names(event_model)`

#### Parameters {#tracked_field_names-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="tracked_field_names-param-event_model">event_model</span> |  | yes |  |  |

### Source {#tracked_field_names-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:1149`

## `workflow_identity` {#workflow_identity}

Name a workflow the way a change does: its code, and the app and model it was written for.

A workflow code is unique among live workflows but not over time, so a code alone cannot say
which workflow a change means once another model has taken that code over. These two columns are
recorded on the workflow itself for exactly this, and they survive the content type going away.

### Signature {#workflow_identity-signature}

`workflow_identity(workflow_event)`

#### Parameters {#workflow_identity-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="workflow_identity-param-workflow_event">workflow_event</span> |  | yes |  |  |

### Source {#workflow_identity-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:1036`

## `workflow_migration_action` {#workflow_migration_action}

Group every write a generated workflow migration makes under one action.

The events a migration writes are attributed to the system user and labelled with the migration
that wrote them, so reading history back separates a migration's writes from a person's edit.
Nothing else in the migration needs to know about it: the triggers record whatever the block
writes, under whatever context is open.

The user model is read through the migration's own registry, because a migration must not depend
on the shape the live model has now.

### Signature {#workflow_migration_action-signature}

`workflow_migration_action(apps, change_reason)`

#### Parameters {#workflow_migration_action-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="workflow_migration_action-param-apps">apps</span> |  | yes |  |  |
| <span id="workflow_migration_action-param-change_reason">change_reason</span> |  | yes |  |  |

### Source {#workflow_migration_action-source}

`server/vueda/workflow/management/commands/makeworkflowmigrations.py:162`

## Source

`server/vueda/workflow/management/commands/makeworkflowmigrations.py`
