update()
Aktualisiert ein bestehendes Objekt auf dem Server. Intern wird dms.XMLUpdate verwendet. Die übergebene Modell-Instanz wird nicht verändert.
ECM-Modell-Referenz — vollständige Beschreibung von system.is_modified, system.modified_fields, system.modified_table_fields, system.has_removed_table_rows, system.requires_table_field_replacement und der Änderungsverfolgung.
Wurden keine Felder geändert und keine Dateien übergeben, wird der Server-Aufruf standardmäßig übersprungen. Mit force=True kann der Aufruf erzwungen werden.
Wird die aktualisierte Instanz direkt nach dem Speichern benötigt, ist update_and_get() die kompaktere Alternative.
1. Signatur
-
Sync
-
Async
ecm.dms.update(
model: T,
files: list[JobRequestFile] | None = None,
replace_files: bool = True,
force: bool = False,
*,
check_mandatory: bool = True,
replace_table_fields: bool | None = None,
) -> None
await ecm.dms.update(
model: T,
files: list[JobRequestFile] | None = None,
replace_files: bool = True,
force: bool = False,
*,
check_mandatory: bool = True,
replace_table_fields: bool | None = None,
) -> None
2. Parameter
| Name | Typ | Beschreibung |
|---|---|---|
|
|
Die zu aktualisierende Modell-Instanz. Muss vom Server geladen worden sein, damit |
|
|
Optionale Dateiliste für das Dokument. Nur für |
|
|
Wenn |
|
|
Wenn |
|
|
Wenn |
|
|
Überschreibt die automatische Steuerung der Option |
|
|
4. Automatisches Überspringen
Wenn alle der folgenden Bedingungen zutreffen, wird der Server-Aufruf ohne Fehler übersprungen:
-
force=False(Standard) -
model.system.is_modifiedistFalse— keine Felder wurden geändert -
filesistNone
Das Änderungsprotokoll (is_modified, modified_fields, modified_table_fields) wird vom Modell automatisch beim Setzen von Feldwerten geführt. Nur diese tatsächlich geänderten Felder werden serialisiert — unveränderte Felder bleiben dem Server fern und werden nicht überschrieben.
Tabellenfelder werden differenziert behandelt:
-
Wurde eine geladene Zeile verändert, entfernt oder ersetzt (d. h.
system.requires_table_field_replacementistTrue), wird das Tabellenfeld komplett neu übertragen und der Server-Aufruf erhält automatischREPLACETABLEFIELDS=1, sodass der Server die gesamte Tabelle ersetzt. -
Wurden nur neue Zeilen angefügt, werden ausschließlich diese neuen Zeilen übertragen — der Server-Default „APPEND" verhindert Duplikate der geladenen Zeilen.
-
Tabellenfelder ohne Änderung werden gar nicht in der XML aufgenommen und bleiben serverseitig unangetastet.
Diese Automatik lässt sich über den Parameter replace_table_fields überschreiben: True erzwingt REPLACETABLEFIELDS=1 (auch bei reinem Anhängen), False unterdrückt es (auch bei erkannter Änderung). None (Standard) belässt die oben beschriebene automatische Erkennung.
5. Feld leeren
Wird ein geladenes Feld auf None gesetzt, leert der Client es auf dem Server. Das Feld wird mit
field_function="NULL" übertragen, sodass der gespeicherte Wert entfernt und nicht unverändert
gelassen wird:
folder = ecm.dms.get(InvoiceFolder, 12345)
folder.Year = None # zuvor gesetztes Feld zurücksetzen
ecm.dms.update(folder) # der Server leert das Feld (field_function="NULL")
Die Änderungsverfolgung wertet None nur dann als Änderung, wenn der vom Server geladene Wert nicht
None war; ein Leeren wird also genau einmal gesendet, ein bereits leeres Feld nicht erneut. Bei
insert() wird ein None-Feld einfach weggelassen — bei einer Neuanlage
gibt es nichts zu leeren.
6. Schreibbare Systemfelder
Systemfelder (SystemFields-Enum) werden standardmäßig aus der dms.XMLUpdate-XML herausgefiltert, da der enaio-Server fast alle mit ECMAccessDeniedException („The specified system field cannot be changed by the user") ablehnt. Eine Allowlist WRITABLE_SYSTEM_FIELDS (in ecmind_blue_client.const) listet die wenigen Felder, die der Server tatsächlich akzeptiert:
| Feld | Verhalten |
|---|---|
|
String-Feld. Insert + Update. Hält die Referenz auf das Dokument im externen Archivsystem; in Kombination mit |
|
Int-Feld. Nur Update. Beim Insert verlangt der Server, dass |
|
String-Feld (Owner). Insert + Update. Der Wert muss der Benutzername sein (z. B. |
Nicht über <Field> verfügbar, sondern als XML-Attribute auf <Object>/<ObjectType> gepflegt und über andere APIs (z. B. insert(), move()) gesteuert: OBJECT_MAIN (= maintype), OBJECT_CO (= cotype), OBJECT_ID (= object_id), SDSTA_ID/SDREG_ID/FOLDERID/REGISTERID/… (= folder_id/register_id/…). Diese liefern als <Field> ebenfalls ECMAccessDeniedException zurück.
Weitere bislang nicht entdeckte schreibbare Systemfelder können nachträglich in WRITABLE_SYSTEM_FIELDS ergänzt werden, ohne Modelländerungen.
from ecmind_blue_client import WRITABLE_SYSTEM_FIELDS
# Programmatisch erweitern (Run-time; persistiert nicht):
WRITABLE_SYSTEM_FIELDS.add("OBJECT_AVID")
7. Ausnahmen
ValueError-
model.system.idistNone(Objekt wurde nicht vom Server geladen) odercheck_mandatory=Trueund ein Pflichtfeld ist nicht gesetzt, oder ein schreibgeschütztes Feld (ECMField(read_only=…)) wurde geändert — siehe ECM-Modell. TypeError-
fileswurde für ein Ordner- oder Register-Modell übergeben.
8. Beispiele
8.1. Einfaches Feldupdate
-
Sync
-
Async
folder = ecm.dms.get(InvoiceFolder, 12345)
folder.Title = "Rechnung 2024 (aktualisiert)"
ecm.dms.update(folder)
folder = await ecm.dms.get(InvoiceFolder, 12345)
folder.Title = "Rechnung 2024 (aktualisiert)"
await ecm.dms.update(folder)
8.2. Dokument mit Datei ersetzen
-
Sync
-
Async
from ecmind_blue_client.rpc import JobRequestFileFromPath
doc = ecm.dms.get(InvoiceDocument, 42)
doc.Title = "Rechnung Nr. 42 (korrigiert)"
ecm.dms.update(
doc,
files=[JobRequestFileFromPath("/tmp/rechnung_v2.pdf")],
replace_files=True, # vorhandene Dateien ersetzen (Standard)
)
from ecmind_blue_client.rpc import JobRequestFileFromPath
doc = await ecm.dms.get(InvoiceDocument, 42)
doc.Title = "Rechnung Nr. 42 (korrigiert)"
await ecm.dms.update(
doc,
files=[JobRequestFileFromPath("/tmp/rechnung_v2.pdf")],
replace_files=True,
)
8.3. Datei anhängen statt ersetzen
-
Sync
-
Async
from ecmind_blue_client.rpc import JobRequestFileFromPath
doc = ecm.dms.get(InvoiceDocument, 42)
ecm.dms.update(
doc,
files=[JobRequestFileFromPath("/tmp/anhang.pdf")],
replace_files=False, # Datei hinzufügen, bestehende behalten
)
from ecmind_blue_client.rpc import JobRequestFileFromPath
doc = await ecm.dms.get(InvoiceDocument, 42)
await ecm.dms.update(
doc,
files=[JobRequestFileFromPath("/tmp/anhang.pdf")],
replace_files=False,
)
8.4. Update erzwingen
Nützlich, wenn externe Logik eine Neuübermittlung erfordert, obwohl keine Felder geändert wurden:
-
Sync
-
Async
folder = ecm.dms.get(InvoiceFolder, 12345)
# keine Feldänderung — ohne force=True würde der Aufruf übersprungen
ecm.dms.update(folder, force=True)
folder = await ecm.dms.get(InvoiceFolder, 12345)
await ecm.dms.update(folder, force=True)
8.5. Pflichtfeldprüfung deaktivieren
-
Sync
-
Async
folder = ecm.dms.get(InvoiceFolder, 12345)
folder.Title = None # Pflichtfeld leeren
# check_mandatory=False: kein Fehler, Pflichtfeldprüfung auch serverseitig deaktiviert
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)
9. Siehe auch
-
update_and_get() — kombiniert
update()undget()in einem Aufruf, wenn die aktualisierte Instanz benötigt wird -
insert() — legt ein neues Objekt an
-
get() — lädt ein einzelnes Objekt vom Server