F)
Feldbearbeitung
Daten, die spezifisch für einen Datensatz sind, sollten in diesem Datensatz gespeichert werden. Lassen Sie uns daher unseren Lehrkräften ein neues Biografie-Feld hinzufügen: Für Datensatzfelder können Vorlagen eine spezielle t-field-Direktive verwenden, die es ermöglicht, den Feldinhalt von der Website aus über feldspezifische Schnittstellen zu bearbeiten. Ändern Sie die Personenvorlage so, dass sie t-field verwendet: Starten Sie Odoo neu und aktualisieren Sie das Modul. Es gibt jetzt einen Platzhalter unter dem Namen des Lehrers und eine neue Zone für Blöcke im Bearbeitungsmodus. Der Name des Lehrers ist ebenfalls editierbar, und beim Speichern ist die Änderung auf der Indexseite sichtbar.t-field kann auch Formatierungsoptionen annehmen, die vom genauen Feld abhängen. Wenn wir zum Beispiel das Änderungsdatum für den Datensatz eines Lehrers anzeigen
Formularansichten
Formulare werden zum Erstellen und Bearbeiten einzelner Datensätze verwendet, deren Wurzelelement <form> ist. Sie setzen sich aus übergeordneten Strukturelementen (Gruppen, Notizbücher) und interaktiven Elementen (Schaltflächen und Felder) zusammen.
Formularansicht Felder
Eine häufige Anforderung ist die Erweiterung der Webformularansicht um neue Möglichkeiten der Anzeige von Feldern.
Alle eingebauten Felder haben eine Standard-Implementierung für die Anzeige. Ein neues Formular-Widget kann erforderlich sein, um mit einem neuen Feldtyp (z. B. einem GIS-Feld) korrekt zu interagieren oder um neue Darstellungen und Möglichkeiten zur Interaktion mit vorhandenen Feldtypen bereitzustellen (z. B. Validierung von Char-Feldern, die E-Mail-Adressen enthalten sollen, und deren Anzeige als E-Mail-Links).
Um explizit anzugeben, welches Formular-Widget für die Anzeige eines Feldes verwendet werden soll, verwenden Sie einfach das Attribut widget in der XML-Beschreibung der Ansicht:
- dasselbe Widget sowohl im "Ansicht"- (schreibgeschützt) als auch im "Ausgabe"-Modus einer Formularansicht verwendet wird, ist es nicht möglich, ein Widget in dem einen und ein anderes Widget in dem anderen zu verwenden
- und ein bestimmtes Feld (Name) kann nicht mehrfach im selben Formular verwendet werden
- ein Widget kann den aktuellen Modus der Formularansicht ignorieren und sowohl in der Ansicht als auch in der Ausgabe gleich bleiben
Felder werden von der Formularansicht instanziiert, nachdem sie ihre XML-Beschreibung gelesen und die entsprechende HTML-Darstellung dieser Beschreibung erstellt hat. Danach kommuniziert die Formularansicht mit den Feldobjekten über einige Methoden. Diese Methoden werden durch die FieldInterface-Schnittstelle definiert. Fast alle Felder erben von der abstrakten Klasse AbstractField. Diese Klasse definiert einige Standardmechanismen, die von den meisten Feldern implementiert werden müssen.
Hier sind einige der Aufgaben einer Feldklasse:
- Die Feldklasse muss den Wert des Feldes anzeigen und dem Benutzer erlauben, ihn zu bearbeiten.
- Sie muss die 3 Feldattribute, die in allen Feldern von Odoo verfügbar sind, korrekt implementieren. Die Klasse AbstractField implementiert bereits einen Algorithmus, der den Wert dieser Attribute dynamisch berechnet (sie können sich jederzeit ändern, da sich ihr Wert in Abhängigkeit vom Wert anderer Felder ändert). Ihre Werte werden in Widget-Eigenschaften gespeichert (die Widget-Eigenschaften wurden weiter oben in diesem Handbuch erläutert). Es liegt in der Verantwortung jeder Feldklasse, diese Widget-Eigenschaften zu überprüfen und in Abhängigkeit von ihren Werten dynamisch anzupassen. Hier finden Sie eine Beschreibung jeder dieser Eigenschaften:
erforderlich
Das Feld muss vor dem Speichern einen Wert haben. Wenn required true ist und das Feld keinen Wert hat, muss die Methode is_valid() des Feldes false zurückgeben.
unsichtbar
Wenn dies wahr ist, muss das Feld unsichtbar sein. Die Klasse AbstractField hat bereits eine grundlegende Implementierung dieses Verhaltens, die für die meisten Felder passt.
schreibgeschützt
Wenn der Wert true ist, darf das Feld nicht vom Benutzer bearbeitet werden können. Die meisten Felder in Odoo haben je nach dem Wert von readonly ein völlig anderes Verhalten. Als Beispiel zeigt das FieldChar ein HTML <input> an, wenn es editierbar ist und zeigt einfach den Text an, wenn es schreibgeschützt ist. Das bedeutet auch, dass es viel mehr Code hat, den es bräuchte, um nur ein Verhalten zu implementieren, aber dies ist notwendig, um eine gute Benutzererfahrung zu gewährleisten.
Felder haben zwei Methoden, set_value() und get_value(), die von der Formularansicht aufgerufen werden, um ihr den anzuzeigenden Wert zu geben und den vom Benutzer eingegebenen neuen Wert zurückzubekommen. Diese Methoden müssen in der Lage sein, den vom Odoo-Server gegebenen Wert zu verarbeiten, wenn ein read() auf einem Modell ausgeführt wird, und einen gültigen Wert für ein write() zurückzugeben. Denken Sie daran, dass die JavaScript/Python-Datentypen, die verwendet werden, um die von read() und write() übergebenen Werte darzustellen, in Odoo nicht notwendigerweise dieselben sind. Wenn Sie z.B. ein many2one lesen, ist es immer ein Tupel, dessen erster Wert die ID des angezeigten Datensatzes ist und der zweite der Name get (z.B.: (15, "Agrolait")). Wenn Sie aber ein many2one schreiben, muss es ein einzelner Integer sein, kein Tupel mehr. AbstractField hat eine Standardimplementierung dieser Methoden, die für einfache Datentypen gut funktioniert und eine Widget-Eigenschaft namens value setzt.
Bitte beachten Sie, dass Sie zum besseren Verständnis der Implementierung von Feldern unbedingt die Definition der Schnittstelle FieldInterface und der Klasse AbstractField direkt im Code des Odoo-Webclients ansehen sollten.
Erstellen eines neuen Feldtyps
In diesem Teil wird erklärt, wie Sie einen neuen Feldtyp erstellen. Als Beispiel wird hier die Klasse FieldChar neu implementiert und nach und nach jeder Teil erklärt
Einfaches Nur-Lese-Feld
Hier ist eine erste Implementierung, die nur Text anzeigt. Der Benutzer kann den Inhalt des Felds nicht ändern.
In diesem Beispiel deklarieren wir eine Klasse namens FieldChar2, die von AbstractField erbt. Wir registrieren diese Klasse auch in der Registry instance.web.form.widgets unter dem Schlüssel char2. Dadurch können wir dieses neue Feld in jeder Formularansicht verwenden, indem wir widget="char2" im <field/>-Tag in der XML-Deklaration der Ansicht angeben.
In diesem Beispiel definieren wir eine einzige Methode: render_value(). Alles, was sie tut, ist, den Wert der Widget-Eigenschaft anzuzeigen. Das sind zwei Werkzeuge, die von der Klasse AbstractField definiert werden. Wie bereits erläutert, wird die Formularansicht die Methode set_value() des Feldes aufrufen, um den anzuzeigenden Wert zu setzen. Diese Methode hat bereits eine Standardimplementierung in AbstractField, die einfach den Wert der Widget-Eigenschaft setzt. AbstractField beobachtet auch das change:value-Ereignis an sich selbst und ruft die Methode render_value() auf, wenn es eintritt. Daher ist render_value() eine praktische Methode, die in untergeordneten Klassen implementiert werden kann, um jedes Mal, wenn sich der Wert des Feldes ändert, eine Operation auszuführen.
In der init()-Methode legen wir auch den Standardwert des Feldes fest, wenn in der Formularansicht keiner angegeben ist (hier nehmen wir an, dass der Standardwert eines char-Feldes ein leerer String sein soll).
Schreib-Lese-Feld
Nur-Lese-Felder, die den Inhalt nur anzeigen und dem Benutzer nicht erlauben, ihn zu ändern, können nützlich sein, aber die meisten Felder in Odoo erlauben auch die Bearbeitung. Das macht die Feldklassen komplizierter, vor allem weil Felder sowohl den bearbeitbaren als auch den nicht bearbeitbaren Modus beherrschen sollen, diese Modi oft völlig unterschiedlich sind (aus Gründen des Designs und der Benutzerfreundlichkeit) und die Felder in der Lage sein müssen, jederzeit zwischen den Modi zu wechseln.
Um zu wissen, in welchem Modus das aktuelle Feld sein soll, setzt die Klasse AbstractField eine Widget-Eigenschaft namens effective_readonly. Das Feld sollte auf Änderungen in dieser Widget-Eigenschaft achten und entsprechend den richtigen Modus anzeigen.
Beispiel:
In der start()-Methode (die sofort aufgerufen wird, nachdem ein Widget an das DOM angehängt wurde) binden wir an das Ereignis change:effective_readonly. Das erlaubt uns, das Feld jedes Mal neu anzuzeigen, wenn sich die Widget-Eigenschaft effective_readonly ändert. Dieser Event-Handler ruft display_field() auf, das auch direkt in start() aufgerufen wird. Dieses display_field() wurde speziell für dieses Feld erstellt, es handelt sich nicht um eine Methode, die in AbstractField oder einer anderen Klasse definiert ist. Wir können diese Methode verwenden, um den Inhalt des Feldes in Abhängigkeit vom aktuellen Modus anzuzeigen.
Von nun an ist die Konzeption dieses Feldes typisch, außer dass es eine Menge Überprüfungen gibt, um den Zustand der effective_readonly-Eigenschaft zu kennen:
- In der QWeb-Vorlage, die zur Anzeige des Inhalts des Widgets verwendet wird, wird ein <input type="text" /> angezeigt, wenn wir uns im Schreib-Lese-Modus befinden, und nichts Besonderes im Nur-Lese-Modus.
- In der Methode display_field() müssen wir auf das Änderungsereignis des <input type="text" /> binden, um zu wissen, wann der Benutzer den Wert geändert hat. Wenn dies geschieht, rufen wir die Methode internal_set_value() mit dem neuen Wert des Feldes auf. Dies ist eine Komfortmethode, die von der Klasse AbstractField bereitgestellt wird. Diese Methode setzt einen neuen Wert in der value-Eigenschaft, löst aber keinen Aufruf von render_value() aus (was auch nicht notwendig ist, da der <input type="text" /> bereits den richtigen Wert enthält).
- In render_value() verwenden wir einen völlig anderen Code, um den Wert des Feldes anzuzeigen, je nachdem, ob wir uns im schreibgeschützten oder im schreibgeschützten Modus befinden.
Formularansicht - Benutzerdefinierte Widgets
Formularfelder werden zur Bearbeitung eines einzelnen Feldes verwendet und sind untrennbar mit einem Feld verbunden. Da dies einschränkend sein kann, ist es auch möglich, Formular-Widgets zu erstellen, die nicht so eingeschränkt sind und weniger Bindungen an einen bestimmten Lebenszyklus haben.
Diese Art von Widget wird einfach von der Formularansicht während der Erstellung des HTML entsprechend der XML-Definition erstellt. Sie haben Eigenschaften mit den Feldern gemeinsam (z. B. die effective_readonly-Eigenschaft), aber ihnen ist kein genaues Feld zugeordnet. Und so haben sie auch keine Methoden wie get_value() und set_value(). Sie müssen von der abstrakten Klasse FormWidget erben.
Formular-Widgets können mit Formularfeldern interagieren, indem sie auf ihre Änderungen hören und ihre Werte abrufen oder ändern. Sie können über ihr field_manager-Attribut auf Formularfelder zugreifen:
FormWidget ist im Allgemeinen die FormView() selbst, aber die von ihr verwendeten Funktionen sollten sich auf die beschränken, die von FieldManagerMixin() definiert werden, wobei die nützlichsten sind.