Merge pull request #38767 from Abdeali099/delete-custom-fields-utility
feat: added a method to delete custom_fields
This commit is contained in:
commit
8054844193
2 changed files with 99 additions and 0 deletions
|
|
@ -443,3 +443,53 @@ def _update_fieldname_references(field: CustomField, old_fieldname: str, new_fie
|
|||
"insert_after",
|
||||
new_fieldname,
|
||||
)
|
||||
|
||||
|
||||
def delete_custom_fields(custom_fields: dict, bypass_hooks: bool = False):
|
||||
"""
|
||||
Delete custom fields from doctypes.
|
||||
|
||||
:param custom_fields: Dict mapping doctype to field names.
|
||||
:param bypass_hooks: If `True`, fast raw delete (skips hooks (doc events like on_trash)).
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
delete_custom_fields({"Address": ["custom_a", "custom_b"]})
|
||||
|
||||
delete_custom_fields({"ToDo": [{"fieldname": "cf_1"}]}, bypass_hooks=True)
|
||||
````
|
||||
"""
|
||||
for doctype, fields in custom_fields.items():
|
||||
fieldnames = []
|
||||
|
||||
if isinstance(fields, (list, tuple, set)):
|
||||
for field in fields:
|
||||
if isinstance(field, str):
|
||||
fieldnames.append(field)
|
||||
elif isinstance(field, dict) and field.get("fieldname"):
|
||||
fieldnames.append(field["fieldname"])
|
||||
|
||||
if not fieldnames:
|
||||
continue
|
||||
|
||||
fieldnames = tuple(set(fieldnames))
|
||||
|
||||
if bypass_hooks:
|
||||
frappe.db.delete(
|
||||
"Custom Field",
|
||||
{
|
||||
"fieldname": ("in", fieldnames),
|
||||
"dt": doctype,
|
||||
},
|
||||
)
|
||||
frappe.clear_cache(doctype=doctype)
|
||||
else:
|
||||
custom_field_names = frappe.get_all(
|
||||
"Custom Field",
|
||||
filters={"fieldname": ("in", fieldnames), "dt": doctype},
|
||||
pluck="name",
|
||||
)
|
||||
|
||||
for custom_field_name in custom_field_names:
|
||||
frappe.get_doc("Custom Field", custom_field_name).delete(ignore_permissions=True, force=True)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ import frappe
|
|||
from frappe.custom.doctype.custom_field.custom_field import (
|
||||
create_custom_field,
|
||||
create_custom_fields,
|
||||
delete_custom_fields,
|
||||
rename_fieldname,
|
||||
)
|
||||
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
|
||||
from frappe.tests import IntegrationTestCase
|
||||
|
||||
|
||||
|
|
@ -183,3 +185,50 @@ class TestCustomField(IntegrationTestCase):
|
|||
self.assertFalse(doc.get(old))
|
||||
|
||||
field.delete()
|
||||
|
||||
def test_delete_custom_fields(self):
|
||||
doctype = "ToDo"
|
||||
fields = [
|
||||
{
|
||||
"fieldname": f"test_delete_{frappe.generate_hash(length=5)}",
|
||||
"fieldtype": "Data",
|
||||
"insert_after": "status",
|
||||
}
|
||||
for _ in range(4)
|
||||
]
|
||||
fieldnames = [f["fieldname"] for f in fields]
|
||||
|
||||
create_custom_fields({doctype: fields})
|
||||
|
||||
# create property setters for fields deleted via safe path (hooks should clean these up)
|
||||
for fieldname in fieldnames[:2]:
|
||||
make_property_setter(doctype, fieldname, "hidden", "1", "Check")
|
||||
|
||||
def field_exists(fieldname):
|
||||
return frappe.db.exists("Custom Field", {"fieldname": fieldname, "dt": doctype})
|
||||
|
||||
def property_setter_exists(fieldname):
|
||||
return frappe.db.exists("Property Setter", {"doc_type": doctype, "field_name": fieldname})
|
||||
|
||||
for fieldname in fieldnames:
|
||||
self.assertTrue(field_exists(fieldname))
|
||||
for fieldname in fieldnames[:2]:
|
||||
self.assertTrue(property_setter_exists(fieldname))
|
||||
|
||||
# 1
|
||||
delete_custom_fields({doctype: [fieldnames[0], fieldnames[0]]})
|
||||
self.assertFalse(field_exists(fieldnames[0]))
|
||||
self.assertFalse(property_setter_exists(fieldnames[0]))
|
||||
|
||||
# 2
|
||||
delete_custom_fields({doctype: [{"fieldname": fieldnames[1]}]})
|
||||
self.assertFalse(field_exists(fieldnames[1]))
|
||||
self.assertFalse(property_setter_exists(fieldnames[1]))
|
||||
|
||||
# 3
|
||||
delete_custom_fields({doctype: [fieldnames[2], fieldnames[2]]}, bypass_hooks=True)
|
||||
self.assertFalse(field_exists(fieldnames[2]))
|
||||
|
||||
# 4
|
||||
delete_custom_fields({doctype: [{"fieldname": fieldnames[3]}]}, bypass_hooks=True)
|
||||
self.assertFalse(field_exists(fieldnames[3]))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue