From 9a0636bf915560068d2da195d386fe8145201cfc Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Sat, 8 Mar 2025 14:28:19 +0530 Subject: [PATCH] perf: fetch existing fields beforehand --- .../doctype/custom_field/custom_field.py | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/frappe/custom/doctype/custom_field/custom_field.py b/frappe/custom/doctype/custom_field/custom_field.py index bac0d19a3e..722cc29c54 100644 --- a/frappe/custom/doctype/custom_field/custom_field.py +++ b/frappe/custom/doctype/custom_field/custom_field.py @@ -316,6 +316,14 @@ def create_custom_fields(custom_fields: dict, ignore_validate=False, update=True :param custom_fields: example `{'Sales Invoice': [dict(fieldname='test')]}`""" + def process_field_update(field): + nonlocal updated + + updated = True + + # handles edge case of same field being updated multiple times + existing_custom_fields[(field.dt, field.fieldname)] = field.__dict__ + try: frappe.flags.in_create_custom_fields = True doctypes_to_update = set() @@ -323,10 +331,12 @@ def create_custom_fields(custom_fields: dict, ignore_validate=False, update=True if frappe.flags.in_setup_wizard: ignore_validate = True + existing_custom_fields = get_existing_custom_fields(custom_fields) + for doctypes, fields in custom_fields.items(): if isinstance(fields, dict): # only one field - fields = [fields] + fields = (fields,) if isinstance(doctypes, str): # only one doctype @@ -336,19 +346,19 @@ def create_custom_fields(custom_fields: dict, ignore_validate=False, update=True updated = False for df in fields: - field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": df["fieldname"]}) + field = existing_custom_fields.get((doctype, df["fieldname"])) if not field: try: df = df.copy() df["owner"] = "Administrator" - create_custom_field(doctype, df, ignore_validate=ignore_validate) - updated = True + custom_field = create_custom_field(doctype, df, ignore_validate=ignore_validate) + process_field_update(custom_field) except frappe.exceptions.DuplicateEntryError: pass elif update: - custom_field = frappe.get_doc("Custom Field", field) + custom_field = frappe.get_doc({"doctype": "Custom Field", **field}) original_values = custom_field.__dict__.copy() custom_field.update(df) @@ -357,7 +367,7 @@ def create_custom_fields(custom_fields: dict, ignore_validate=False, update=True custom_field.flags.ignore_validate = True custom_field.save() - updated = True + process_field_update(custom_field) if updated: doctypes_to_update.add(doctype) @@ -370,6 +380,19 @@ def create_custom_fields(custom_fields: dict, ignore_validate=False, update=True frappe.flags.in_create_custom_fields = False +def get_existing_custom_fields(custom_fields): + doctypes_to_fetch = set() + for doctypes in custom_fields: + if isinstance(doctypes, str): + doctypes = (doctypes,) + + for doctype in doctypes: + doctypes_to_fetch.add(doctype) + + existing_fields = frappe.get_all("Custom Field", filters={"dt": ("in", doctypes_to_fetch)}, fields="*") + return {(field.dt, field.fieldname): field for field in existing_fields} + + @frappe.whitelist() def rename_fieldname(custom_field: str, fieldname: str): frappe.only_for("System Manager")