diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index ea4264212b..18b9212e1d 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -242,7 +242,7 @@ class BaseDocument(object): return value - def get_valid_dict(self, sanitize=True, convert_dates_to_str=False, ignore_nulls = False): + def get_valid_dict(self, sanitize=True, convert_dates_to_str=False, ignore_nulls=False, ignore_virtual=False): d = frappe._dict() for fieldname in self.meta.get_valid_columns(): d[fieldname] = self.get(fieldname) @@ -254,6 +254,10 @@ class BaseDocument(object): df = self.meta.get_field(fieldname) if df and df.get("is_virtual"): + if ignore_virtual: + del d[fieldname] + continue + from frappe.utils.safe_exec import get_safe_globals if d[fieldname] is None: @@ -412,7 +416,11 @@ class BaseDocument(object): self.created_by = self.modified_by = frappe.session.user # if doctype is "DocType", don't insert null values as we don't know who is valid yet - d = self.get_valid_dict(convert_dates_to_str=True, ignore_nulls = self.doctype in DOCTYPES_FOR_DOCTYPE) + d = self.get_valid_dict( + convert_dates_to_str=True, + ignore_nulls=self.doctype in DOCTYPES_FOR_DOCTYPE, + ignore_virtual=True, + ) columns = list(d) try: @@ -766,7 +774,7 @@ class BaseDocument(object): type_map = frappe.db.type_map - for fieldname, value in self.get_valid_dict().items(): + for fieldname, value in self.get_valid_dict(ignore_virtual=True).items(): df = self.meta.get_field(fieldname) if not df or df.fieldtype == 'Check': @@ -844,7 +852,7 @@ class BaseDocument(object): if frappe.flags.in_install: return - for fieldname, value in self.get_valid_dict().items(): + for fieldname, value in self.get_valid_dict(ignore_virtual=True).items(): if not value or not isinstance(value, str): continue diff --git a/frappe/patches.txt b/frappe/patches.txt index db9610a767..0d2a6162c2 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -184,6 +184,7 @@ frappe.patches.v13_0.queryreport_columns frappe.patches.v13_0.jinja_hook frappe.patches.v13_0.update_notification_channel_if_empty frappe.patches.v13_0.set_first_day_of_the_week +execute:frappe.reload_doc('custom', 'doctype', 'custom_field') frappe.patches.v14_0.update_workspace2 # 20.09.2021 frappe.patches.v14_0.save_ratings_in_fraction #23-12-2021 frappe.patches.v14_0.transform_todo_schema diff --git a/frappe/tests/test_document.py b/frappe/tests/test_document.py index a0c44c5c72..4d399a9c94 100644 --- a/frappe/tests/test_document.py +++ b/frappe/tests/test_document.py @@ -271,6 +271,10 @@ class TestDocument(unittest.TestCase): """Virtual fields are accessible via API and Form views, whenever .as_dict is invoked """ frappe.db.delete("Custom Field", {"dt": "Note", "fieldname":"age"}) + note = frappe.new_doc("Note") + note.content = "some content" + note.title = frappe.generate_hash(length=20) + note.insert() def patch_note(): return patch("frappe.controllers", new={frappe.local.site: {'Note': CustomTestNote}})