20100804

Nachtrag zum Thema disabled_fields : weil das ein Feature ist, das wahrscheinlich selten benutzt werden wird, würde Lino in den meisten Anfragen für jeden Record die Info “disabled_fields: []” reinpacken. Machen wir so dass es dieses Pseudofeld nur generiert, wenn lino.reports.Report.disabled_fields nicht None ist.

Ich habe dann doch mit lino.demo begonnen, weil ich sehen wollte, wie die Links im vorigen Absatz funktionieren. Eigentlich könnten Dokumentation und Webseite bis Ende August warten, aber “Sphinx makes programmers want to write documentation”…

Model validation

  • Insert in Persons sagt { msg: “Failed to save : {‘name’: [u’Dieses Feld darf nicht leer sein.’]}”, success: false }.

Das Feld Person.name ist ja nicht vom Benutzer editierbar, sondern wird automatisch aus den Feldern first_name. name und title generiert. Das muss vor jedem Abspeichern gemacht werden.

Erste Idee: einfach in lino.ui.extjs.ext_ui.ExtUI.api_list_view() ein instance.before_save() vor das instance.full_clean() setzen. Aber das funktioniert nicht, wenn ein Model gar keine before_save definiert hat.

Ich könnte natürlich if hasattr(instance,'before_save') testen, aber gibt es nicht bessere Lösungen?

Das wäre doch eigentlich ein Fall für Djangos Model Validation.

Also zweite Idee: before_save kommt weg, und der name wird in einer Model.clean gesetzt. Pech, das geht nicht, weil ja Model.clean_fields() (die sich über das leere Feld beschwert). vor der Model.clean() gerufen wird.

Noch eine Idee: ich definiere name in modlib.contacts.Contact mit einem default, der ja laut Doku ein callable sein kann. Das geht auch nicht, weil Django das Objekt, für das der Standardwert ermittelt werden soll, nicht übergibt. Abgesehen davon sehe ich nicht, wie ich diese Methode dann in Unterklassen neudefinieren könnte.

def name_default(self):
l = filter(lambda x:x,[self.last_name,self.first_name,self.title]) return ” “.join(l)

Also lassen wir das. lino.ui.extjs.ext_ui.ExtUI.api_list_view() macht if hasattr(instance,'before_save') und fertig. Ich bin nicht 100% zufrieden mit diesem System, aber momentan läuft das so, und ich warte bis sich konkrete Problemfälle zeigen.

Der folgende Punkt war übrigens schon seit Längerem fertig:

  • In countries.Countries kann man nicht einfügen. Dieser Report ist ein Sonderfall, weil Country keinen automatischen primary key hat, sondern das Feld isocode dort der pk ist. Das darf natürlich im InsertWrapper und für die ExtraRow (aber nicht für die anderen Zeilen) nicht schreibgeschützt sein.

Kolonnenfilter und ReportConfig

So, jetzt weiter mit der hoffentlich letzten großen Herausforderung vor der Geburt: Kolonnenfilter und (vorher) ReportConfig.

In der Lino.GridPanel.tbar kommen zwei neue Elemente: - eine ComboBox, in der man die verschiedenen ReportConfigs auswählen kann. - einen Button “Save-Config” zum Speichern.

Ein GET eines Reports hat jetzt neben rows, total und title ein neues Attribut configs, das eine einfache Liste der Auswahlmöglichkeiten für diese Combobox ist.

Eine andere (bestehende) ReportConfig lädt man, indem man sie in der Combobox auswählt. ViewReportRequest fragt einen neuen URI-Parameter cfg ab, der den Namen der gewünschten config enthält.

Neue ReportConfigs erstellt man, indem man in der Combobox einen neuen Namen tippt und dann auf “Save Config” klickt. Wenn überhaupt keine ReportConfig existiert. Aber jetzt erstmal Unterbrechung inklusive Mittagspause und Rasenmähen.

django-admin commands

Nach der Unterbrechung habe ich mich ablenken lassen von lino.demo. Die funktioniert ja noch überhaupt nicht. Ich hab was verstanden: um Scripts wie initdb.py, load_tim.py, send_invoices.py durch django-admin commands zu ersetzen, brauche ich wahrscheinlich ein Signal, das bei jedem Start eines Management Tools nach dem Laden der Modelle gefeuert wird… Updated my copy of Django from 13336 to 13467. Aber das ist nicht so dringend, das kommt in die /todo.