perf: fetch existing fields beforehand

This commit is contained in:
Sagar Vora 2025-03-08 14:28:19 +05:30
parent 7503db4160
commit 9a0636bf91

View file

@ -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")