Applications personnalisées
Champs additionnels
Créer des champs personnalisés et des propriétés depuis une application, pour synchroniser plusieurs sites sans l'interface.
Créer des champs additionnels à l'aide d'une application personnalisée
Une application personnalisée peut créer des champs personnalisés et des « Property Setter » par le code. Les mêmes champs arrivent alors sur tous les sites où l'application est installée (développement, recette, production), sans passer par Personnaliser un formulaire.
Principe
- Le hook
after_installcrée les champs à l'installation de l'application. - Le hook
after_migrateles met à jour à chaquebench migrate. - La fonction
create_custom_fieldscrée un champ absent et met à jour un champ existant. - La liste
OLD_FIELDSsupprime les champs que vous ne voulez plus.
Déclarer les hooks
my_app/hooks.py
after_install = "my_app.install.after_install"
after_migrate = "my_app.install.after_migrate"
Écrire le module d'installation
L'exemple ajoute le champ my_app_field après le champ customer_name du type de document Client (Customer).
my_app/install.py
import frappe
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
# The existing OLD_FIELDS will always be deleted first.
# Make sure to include all fields that you create in this list.
# When removing a field from the CUSTOM_FIELDS list, keep its entry in the OLD_FIELDS.
# This will ensure that future migrations will correctly remove obsolete fields.
# The fields will be created in module MODULE.
# Each property setter is deleted and inserted again at every migrate.
# Keep it in the PROPERTY_SETTERS list until it becomes obsolete.
MODULE = "My App"
OLD_FIELDS = [
("Customer", "my_field"),
]
CUSTOM_FIELDS = {
"Customer": [
{
"fieldname": "my_app_field",
"label": "My Field",
"fieldtype": "Data",
"insert_after": "customer_name",
},
],
}
PROPERTY_SETTERS = [
# {
# "name": "DOCTYPE-FIELD-PROPERTY",
# "doc_type": "DOCTYPE",
# "doctype_or_field": "DocField",
# "field_name": "FIELD",
# "property": "PROPERTY",
# "value": "VALUE",
# },
]
def after_install():
after_migrate()
def after_migrate():
for dt, fieldname in OLD_FIELDS:
if name := frappe.db.exists("Custom Field", {"dt": dt, "fieldname": fieldname}):
frappe.delete_doc("Custom Field", name)
# Add `module` property and `insert_after` if missing
for fields in CUSTOM_FIELDS.values():
prev_field = None
for field in fields:
field["module"] = MODULE
if prev_field and not field.get("insert_after"):
field["insert_after"] = prev_field["fieldname"]
prev_field = field
create_custom_fields(CUSTOM_FIELDS)
# Insert property setters
for ps in PROPERTY_SETTERS:
assert ps["name"], "Property Setter name is required"
frappe.delete_doc_if_exists("Property Setter", ps["name"])
doc = frappe.new_doc("Property Setter") # type: ignore
doc.is_system_generated = True
doc.module = MODULE
doc.update(ps)
doc.insert()
Points d'attention
- Gardez dans
OLD_FIELDSchaque champ retiré deCUSTOM_FIELDS. Sans cela, le champ reste sur les sites déjà installés. - Le nom d'un « Property Setter » suit le format
<type de document>-<champ>-<propriété>, par exempleCustomer-customer_group-reqd. Dodock recalcule ce nom à l'insertion : utilisez ce format dansPROPERTY_SETTERS. - Pour un seul « Property Setter »,
frappe.make_property_setter()fait le même travail en un appel. - Préfixez le nom de vos champs (
my_app_…) pour éviter un conflit avec un champ standard ou une autre application.