diff --git a/frappe/model/document.py b/frappe/model/document.py index be0040c7ab..d81a7f44a7 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -1944,8 +1944,6 @@ def unlock_document(doctype: str, name: str): def get_lazy_controller(doctype): - from frappe.model.document import LazyDocument - lazy_controllers = frappe.controllers.setdefault(f"lazy|{frappe.local.site}", {}) if doctype not in lazy_controllers: original_controller = get_controller(doctype) @@ -1967,6 +1965,7 @@ class LazyDocument: """Override Document which eagerly loads child tables""" # This is a map of loaded children, it should get erased whenever load_children_from_db is # called to allow reloading lazily again. + self.flags.lazy_loaded = True for fieldname in self._table_fieldnames: self.__dict__.pop(fieldname, None) @@ -1975,6 +1974,16 @@ class LazyDocument: _ = getattr(self, key, None) return super().get(key, *args, **kwags) + @override + def db_update_all(self): + self.db_update() + for fieldname in self._table_fieldnames: + if fieldname not in self.__dict__: + # Not fetched, can't possibly change so no need to update + continue + for doc in self.get(fieldname): + doc.db_update() + class LazyChildTable: __slots__ = ("doctype", "fieldname") diff --git a/frappe/tests/test_document.py b/frappe/tests/test_document.py index 87dc00efba..78d0e4f7a8 100644 --- a/frappe/tests/test_document.py +++ b/frappe/tests/test_document.py @@ -556,6 +556,18 @@ class TestDocument(IntegrationTestCase): # things accessing __dict__ by default should be updated too self.assertTrue(frappe.get_lazy_doc("User", "Guest").get("roles")) + # Only touched tables and self should be updated + guest = frappe.get_lazy_doc("User", "Guest") + with self.assertQueryCount(1): + guest.db_update_all() + + guest = frappe.get_lazy_doc("User", "Guest") + _ = guest.roles + with self.assertQueryCount(1 + len(guest.roles)): + guest.db_update_all() + + # Save should works, it won't be efficient because internal code will just trigger fetching + # of child tables to resave them. guest.save()