Best Practices for Tracking Field Changes and Updating Submitted Docs in Frappe

Hi everyone,

I’m currently working with the Material Request doctype and have encountered a situation I’d like to ask about.

When updating a field using the ORM / Doc API, like this:

mr = frappe.get_doc("Material Request", mr_name)
mr.status = "Received"
mr.save()

all event hooks such as validate, before_save, and on_update are triggered as expected.

However, if I update a field using the DB API directly, like:
frappe.db.set_value("Material Request", mr_name, "status", "Received")
then none of the ORM event hooks are triggered — which is understandable, since this method bypasses the document lifecycle.

I have two main questions:

  1. Is there a way to listen for or intercept changes made via frappe.db.set_value()?
    For example, I’d like to trigger a function whenever the status field is changed — even if it’s changed using direct DB access.
  2. In some cases, I need to update certain fields on submitted documents (docstatus = 1).
    Since calling .save() on a submitted doc raises the error "Submitted Document cannot be saved.", the only option seems to be using frappe.db.set_value().
    Is there a way to bypass this limitation and still use the ORM safely**, or any other “safe” alternative to update fields on submitted documents?

My goals are:

  • To track or respond to field-level changes regardless of whether they’re made through the ORM or frappe.db.set_value().
  • To safely update allowed fields on submitted documents (like status or custom fields) without relying solely on raw DB operations.

Any guidance or best practices would be much appreciated. Thanks in advance!

1 Like

Hi, does anyone know…?

Hello @SKDragon18

  1. set_value does not trigger any document event.if you want to trigger any document event you need to use doc.save()
    One option is there if you don’t want to execute all event but want to execute any single one you can try as below.

frappe.get_doc(doctype, docname).validate()
frappe.db.set_value(doctype, docname, fieldname, value)

Alternative for above:

doc = frappe.get_doc(doctype, docname)
doc.db_set(fieldname, value)
doc.save()

  1. If you want to change any field after submission and want to use doc.save(), you need to set allow on submit property for that field.

Hope this will help you.

3 Likes