API Controller.docs — Accès statique aux documents
API Controller.docs — Accès statique aux documents
develop). Elle n'existe pas en v5.Les fonctions frappe.get_doc, frappe.new_doc et les autres reçoivent le nom du type de document en texte. La collection docs de la classe contrôleur fait le même travail à partir de la classe elle-même, par exemple ToDo.docs.get(...).
Avantages :
- Les IDE et les analyseurs de code (Pyright, PyCharm…) comprennent le type de retour sans configuration supplémentaire.
- Le nom du Doctype n'est plus passé en tant que chaîne de caractères : les fautes de frappe sont détectées à l'analyse statique.
- Les imports explicites documentent les dépendances entre modules.
Prérequis
La classe controller du Doctype doit déclarer son nom de Doctype via l'attribut _DOCTYPE_NAME :
from frappe.model.document import Document
class ToDo(Document):
_DOCTYPE_NAME = "ToDo"
Dodock ajoute cet attribut aux contrôleurs qu'il génère pour un nouveau type de document.
Tableau de correspondance des méthodes
| Ancienne API (toujours disponible) | Nouvelle API Controller.docs | Description |
|---|---|---|
frappe.get_doc("ToDo", "T-001") | ToDo.docs.get("T-001") | Récupérer un document par son nom |
frappe.get_last_doc("ToDo") | ToDo.docs.last() | Récupérer le dernier document |
frappe.get_last_doc("ToDo", filters={"reference_name": "ABC"}) | ToDo.docs.last({"reference_name": "ABC"}) | Récupérer le dernier document qui correspond à un filtre |
frappe.get_docs("ToDo", {"status": "Open"}) | ToDo.docs.filter({"status": "Open"}) | Récupérer plusieurs documents |
frappe.new_doc("ToDo", status="Open") | ToDo.docs.new(status="Open") | Créer un nouveau document (non enregistré) |
frappe.get_cached_doc("ToDo", "T-001") | ToDo.docs.get("T-001", cached=True) | Récupérer depuis le cache |
frappe.get_lazy_doc("ToDo", "T-001") | ToDo.docs.get("T-001", lazy=True) | Récupérer en mode lazy |
frappe.delete_doc("ToDo", "T-001") | ToDo.docs.get("T-001").delete() | Supprimer un document |
frappe.rename_doc("ToDo", "T-001", "T-002") | ToDo.docs.get("T-001").rename("T-002") | Renommer un document |
docs.get() accepte aussi for_update=True (verrouille la ligne) et check_permission="read" (contrôle l'autorisation). docs.filter() accepte limit, order_by et as_iterator=True (lecture par lots de chunk_size documents). cached et lazy ne se combinent pas.
Exemples d'utilisation
Récupérer un document par son nom
from frappe.desk.doctype.todo.todo import ToDo
todo = ToDo.docs.get("T-001")
print(todo.description)
Créer un nouveau document
from frappe.desk.doctype.todo.todo import ToDo
nouvel_element = ToDo.docs.new(
description="Relancer Maison Verte SARL", # client fictif
status="Open",
assigned_by="administrateur@example.com",
)
nouvel_element.insert()
Filtrer plusieurs documents
from frappe.desk.doctype.todo.todo import ToDo
todos_ouverts = ToDo.docs.filter({"status": "Open"})
for todo in todos_ouverts:
print(todo.name, todo.description)
Récupérer le dernier document créé
from frappe.desk.doctype.todo.todo import ToDo
dernier_todo = ToDo.docs.last()
print(dernier_todo.name)
Récupérer un document depuis le cache
Pour des lectures fréquentes, sans modification du document :
from frappe.desk.doctype.todo.todo import ToDo
todo_cache = ToDo.docs.get("T-001", cached=True)
Renommer un document
from frappe.desk.doctype.todo.todo import ToDo
ToDo.docs.get("T-001").rename("T-002")
Supprimer un document
from frappe.desk.doctype.todo.todo import ToDo
ToDo.docs.get("T-001").delete()
Raccourcir les chemins d'import
Les chemins d'import vers les controllers peuvent être longs. Pour les modules comportant de nombreux Doctypes, vous pouvez exposer les classes dans le fichier __init__.py du dossier doctype :
# monapp/monmodule/doctype/__init__.py
from .mon_doctype.mon_doctype import MonDoctype
Ce qui permet d'écrire :
from monapp.monmodule.doctype import MonDoctype
Cette convention est facultative. Dans un gros module, elle peut créer des conflits de noms.
Déclarer _DOCTYPE_NAME sur votre controller
Pour que Controller.docs fonctionne, chaque classe doit déclarer _DOCTYPE_NAME. Sur les Doctypes existants, ajoutez simplement l'attribut de classe :
from frappe.model.document import Document
class DemandeIntervention(Document): # type de document fictif
_DOCTYPE_NAME = "Demande Intervention"
Sans cet attribut, .docs lève une erreur AttributeError : « … does not define _DOCTYPE_NAME ». .docs n'est accessible que depuis la classe, pas depuis une instance.
Quand utiliser l'ancienne API ?
L'ancienne API reste la bonne solution dans les cas suivants :
- Le nom du Doctype est déterminé dynamiquement (ex. : reçu en paramètre d'une fonction générique).
- Vous écrivez du code partagé entre plusieurs Doctypes sans import spécifique.
- Vous écrivez un script serveur : les imports n'y sont pas disponibles.