From d1ee3005c255562db718feaa9f0830ff085e2f47 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Mon, 28 Mar 2022 17:14:16 +0530 Subject: [PATCH] perf: improve Custom Field insertion time --- .../doctype/custom_field/custom_field.py | 56 +++++++++++-------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/frappe/custom/doctype/custom_field/custom_field.py b/frappe/custom/doctype/custom_field/custom_field.py index af10c6d76a..fdd7bf3134 100644 --- a/frappe/custom/doctype/custom_field/custom_field.py +++ b/frappe/custom/doctype/custom_field/custom_field.py @@ -33,29 +33,40 @@ class CustomField(Document): def before_insert(self): self.set_fieldname() - meta = frappe.get_meta(self.dt, cached=False) - fieldnames = [df.fieldname for df in meta.get("fields")] - - if self.fieldname in fieldnames: - frappe.throw(_("A field with the name '{}' already exists in doctype {}.").format(self.fieldname, self.dt)) def validate(self): + # these imports have been added to avoid cyclical import, should fix in future from frappe.custom.doctype.customize_form.customize_form import CustomizeForm - - meta = frappe.get_meta(self.dt, cached=False) - fieldnames = [df.fieldname for df in meta.get("fields")] - - if self.insert_after=='append': - self.insert_after = fieldnames[-1] - - if self.insert_after and self.insert_after in fieldnames: - self.idx = fieldnames.index(self.insert_after) + 1 - - old_fieldtype = self.db_get('fieldtype') - is_fieldtype_changed = (not self.is_new()) and (old_fieldtype != self.fieldtype) - - if not self.is_virtual and is_fieldtype_changed and not CustomizeForm.allow_fieldtype_change(old_fieldtype, self.fieldtype): - frappe.throw(_("Fieldtype cannot be changed from {0} to {1}").format(old_fieldtype, self.fieldtype)) + from frappe.core.doctype.doctype.doctype import check_fieldname_conflicts + + # don't always get meta to improve performance + # setting idx is just an improvement, not a requirement + if self.is_new() or self.insert_after == "append": + meta = frappe.get_meta(self.dt, cached=False) + fieldnames = [df.fieldname for df in meta.get("fields")] + + if self.is_new() and self.fieldname in fieldnames: + frappe.throw( + _("A field with the name {0} already exists in {1}") + .format(frappe.bold(self.fieldname), self.dt) + ) + + if self.insert_after == "append": + self.insert_after = fieldnames[-1] + + if self.insert_after and self.insert_after in fieldnames: + self.idx = fieldnames.index(self.insert_after) + 1 + + if ( + not self.is_virtual + and (doc_before_save := self.get_doc_before_save()) + and (old_fieldtype := doc_before_save.fieldtype) != self.fieldtype + and not CustomizeForm.allow_fieldtype_change(old_fieldtype, self.fieldtype) + ): + frappe.throw( + _("Fieldtype cannot be changed from {0} to {1}") + .format(old_fieldtype, self.fieldtype) + ) if not self.fieldname: frappe.throw(_("Fieldname not set for Custom Field")) @@ -63,13 +74,12 @@ class CustomField(Document): if self.get('translatable', 0) and not supports_translation(self.fieldtype): self.translatable = 0 - if not self.flags.ignore_validate: - from frappe.core.doctype.doctype.doctype import check_fieldname_conflicts - check_fieldname_conflicts(self) + check_fieldname_conflicts(self) def on_update(self): if not frappe.flags.in_setup_wizard: frappe.clear_cache(doctype=self.dt) + if not self.flags.ignore_validate: # validate field from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype