update()
Updates an existing object on the server using dms.XMLUpdate. The passed model instance is not mutated.
ECM Model reference — for a full description of system.is_modified, system.modified_fields, system.modified_table_fields, system.has_removed_table_rows, system.requires_table_field_replacement, and how change tracking works.
If no fields have been changed and no files are provided, the server call is skipped by default. Pass force=True to send the request regardless.
If the fully populated instance is needed directly after the update, update_and_get() is the more compact alternative.
1. Signature
-
Sync
-
Async
ecm.dms.update(
model: T,
files: list[JobRequestFile] | None = None,
replace_files: bool = True,
force: bool = False,
*,
check_mandatory: bool = True,
) -> None
await ecm.dms.update(
model: T,
files: list[JobRequestFile] | None = None,
replace_files: bool = True,
force: bool = False,
*,
check_mandatory: bool = True,
) -> None
2. Parameters
| Name | Type | Description |
|---|---|---|
|
|
The model instance to update. Must have been loaded from the server so that |
|
|
Optional list of files for the document. Only allowed for |
|
|
When |
|
|
When |
|
|
When |
4. Automatic skip
The server call is silently skipped when all of the following conditions are true:
-
force=False(default) -
model.system.is_modifiedisFalse— no fields have been changed -
filesisNone
The model tracks field changes automatically (is_modified, modified_fields, modified_table_fields). Only the fields you have actually touched are serialised — untouched fields are left alone and never re-sent to the server.
Table fields are handled separately:
-
When a loaded row was modified, removed, or replaced (i.e.
system.requires_table_field_replacementisTrue), the entire current row set is sent andREPLACETABLEFIELDS=1is added automatically so the server replaces the table contents. -
When only new rows were appended, only those new rows are sent — the server’s default APPEND mode keeps the existing rows from being duplicated.
-
Table fields with no changes are omitted from the XML and remain untouched on the server.
5. Writable system fields
System fields (SystemFields enum) are stripped from the dms.XMLUpdate payload by default because the enaio server rejects almost all of them with ECMAccessDeniedException ("The specified system field cannot be changed by the user"). An allowlist WRITABLE_SYSTEM_FIELDS (in ecmind_blue_client.const) names the few that the server actually accepts:
| Field | Behaviour |
|---|---|
|
String field. Insert + update. Holds the reference to the document in the external archive system; together with |
|
Int field. Update only. On insert the server demands that |
|
String field (owner). Insert + update. The value sent must be the target user’s username (e.g. |
Not available through <Field> but maintained as XML attributes on <Object>/<ObjectType> and controlled through other APIs (e.g. insert(), move()): OBJECT_MAIN (= maintype), OBJECT_CO (= cotype), OBJECT_ID (= object_id), SDSTA_ID/SDREG_ID/FOLDERID/REGISTERID/… (= folder_id/register_id/…). These also return ECMAccessDeniedException when sent as <Field>.
Further writable system fields discovered later can simply be added to WRITABLE_SYSTEM_FIELDS without any model changes.
from ecmind_blue_client import WRITABLE_SYSTEM_FIELDS
# Extend programmatically at run-time (not persisted):
WRITABLE_SYSTEM_FIELDS.add("OBJECT_AVID")
6. Exceptions
ValueError-
model.system.idisNone(object was not loaded from the server) orcheck_mandatory=Trueand a required field is not set, or a read-only field (ECMField(read_only=…)) was changed — see ECM model. TypeError-
fileswas provided for a folder or register model.
7. Examples
7.1. Simple field update
-
Sync
-
Async
folder = ecm.dms.get(InvoiceFolder, 12345)
folder.Title = "Invoice 2024 (updated)"
ecm.dms.update(folder)
folder = await ecm.dms.get(InvoiceFolder, 12345)
folder.Title = "Invoice 2024 (updated)"
await ecm.dms.update(folder)
7.2. Replace document file
-
Sync
-
Async
from ecmind_blue_client.rpc import JobRequestFileFromPath
doc = ecm.dms.get(InvoiceDocument, 42)
doc.Title = "Invoice No. 42 (corrected)"
ecm.dms.update(
doc,
files=[JobRequestFileFromPath("/tmp/invoice_v2.pdf")],
replace_files=True, # replace existing files (default)
)
from ecmind_blue_client.rpc import JobRequestFileFromPath
doc = await ecm.dms.get(InvoiceDocument, 42)
doc.Title = "Invoice No. 42 (corrected)"
await ecm.dms.update(
doc,
files=[JobRequestFileFromPath("/tmp/invoice_v2.pdf")],
replace_files=True,
)
7.3. Append file instead of replacing
-
Sync
-
Async
from ecmind_blue_client.rpc import JobRequestFileFromPath
doc = ecm.dms.get(InvoiceDocument, 42)
ecm.dms.update(
doc,
files=[JobRequestFileFromPath("/tmp/attachment.pdf")],
replace_files=False, # add file, keep existing ones
)
from ecmind_blue_client.rpc import JobRequestFileFromPath
doc = await ecm.dms.get(InvoiceDocument, 42)
await ecm.dms.update(
doc,
files=[JobRequestFileFromPath("/tmp/attachment.pdf")],
replace_files=False,
)
7.4. Forcing an update
Useful when external logic requires resubmission even though no fields have changed:
-
Sync
-
Async
folder = ecm.dms.get(InvoiceFolder, 12345)
# no field changes — without force=True the call would be skipped
ecm.dms.update(folder, force=True)
folder = await ecm.dms.get(InvoiceFolder, 12345)
await ecm.dms.update(folder, force=True)
7.5. Disabling mandatory field validation
-
Sync
-
Async
folder = ecm.dms.get(InvoiceFolder, 12345)
folder.Title = None # clear a mandatory field
# check_mandatory=False: no error, obligation check also disabled server-side
ecm.dms.update(folder, check_mandatory=False)
folder = await ecm.dms.get(InvoiceFolder, 12345)
folder.Title = None
await ecm.dms.update(folder, check_mandatory=False)
8. See also
-
update_and_get() — combines
update()andget()in one call when the updated instance is needed -
insert() — creates a new object
-
get() — loads a single object from the server