Seite 1 von 1

Field Annotationen?

Verfasst: Dienstag 4. November 2008, 23:13
von DatenMetzgerX
Hallo zusammen
Ich arbeite im Büro oft mit Java und dort sind Annotationen ja stark vertreten. Leider kann man jetzt in Python jedoch nur Funktionen dekorieren, oder liege ich da falsch?

Mein Problem:
Ich habe eine Model Klasse (Verwende sqlalchemy + elixir) und möchte die Edit / View / List Visuals generisch generieren. Hierfür muss ich jedoch wissen, was ich in ein Label für ein Feld reinschreiben?! Und auch ob der Wert überhaupt angezeigt werden soll.
Hierfür hätte ich mir sowas wie
@Editable(label="Titel")
titel = Field(type=Unicode(255)...)

gewünscht. Somit wüsste ich, das Feld ist mit @Editable annotiert und muss dargestellt werden und als Key für die Übersetzungen soll "Titel" verwendet werden. Alle anderen Werte wie ob der Wert null sein darf, Max Feldlänge etc. könnte ich mir ja denn aus der Field Instanz auslesen.

Gibt es so was in Python... oder suche ich nach der falschen Lösung?

Ach ja grund wieso ich nicht einfach der Feldnamen verwenden möchte ist, dass ich sonst immer eine vordefinierte DB mit den Strings ausliefern müsste. Jedoch soll sich das Programm mit der default Übersetzung selbst in die DB abfüllen wie alle anderen standart Werte.

Gruess + Dank
Micha

Re: Field Annotationen?

Verfasst: Dienstag 4. November 2008, 23:37
von Leonidas
DatenMetzgerX hat geschrieben:Ich arbeite im Büro oft mit Java und dort sind Annotationen ja stark vertreten. Leider kann man jetzt in Python jedoch nur Funktionen dekorieren, oder liege ich da falsch?
Python 3 hat auch Dekoratoren für Klassen und Annotationen in Funktionssignaturen.
DatenMetzgerX hat geschrieben:Mein Problem:
Ich habe eine Model Klasse (Verwende sqlalchemy + elixir) und möchte die Edit / View / List Visuals generisch generieren. Hierfür muss ich jedoch wissen, was ich in ein Label für ein Feld reinschreiben?! Und auch ob der Wert überhaupt angezeigt werden soll.
Hierfür hätte ich mir sowas wie
@Editable(label="Titel")
titel = Field(type=Unicode(255)...)

gewünscht. Somit wüsste ich, das Feld ist mit @Editable annotiert und muss dargestellt werden und als Key für die Übersetzungen soll "Titel" verwendet werden. Alle anderen Werte wie ob der Wert null sein darf, Max Feldlänge etc. könnte ich mir ja denn aus der Field Instanz auslesen.
Ich würde auf den Instanzen einfach irgendwelche Attribute setzen, die man dann später abfragt. Oder ist das bei dir aus irgendeinen Grund nicht machbar?

Verfasst: Mittwoch 5. November 2008, 09:51
von DatenMetzgerX
Demfall heisst es warten.

Machbar ist es, finde ich aber nicht sehr lesbar. Somit muss ich mir als Entwickler alle Werte zuerst aus der Klasse zusammen suchen (auch wenn alles evtl gleich untereinander steht. Aber dann habe ich schon mehrere Zeile für 1 Column. Emfpinde ich einfach als unesthetisch ;)

Code: Alles auswählen

  #schöner
  @editable(label="Titel")
  titel = Field(type=Unicode(255))

  #weniger toll
  titel = Field(type=Unicode(255))
  titel.label = "Titel" 
  titel.editable = true

Aber dankschön :)

Verfasst: Mittwoch 5. November 2008, 09:55
von Leonidas
Naja, also so schlimm finde ich das nun wirklich nicht:

Code: Alles auswählen

  @editable(label="Titel")
  titel = Field(type=Unicode(255))

  # vs
  titel = Field(type=Unicode(255))
  editable(titel, label="Titel")
Letztendlich einfach manuell dekorieren.

Verfasst: Mittwoch 5. November 2008, 10:42
von DatenMetzgerX
Hat was! Das habe ich jetzt gar nicht in betracht gezogen. Wäe eine Vorstufe für die Dekoratoren in Py3.0. Doch dies gefällt mir.
Danke vielmals!

Verfasst: Mittwoch 5. November 2008, 10:43
von sma
Ich glaube, es ist nicht gut, Modell und Darstellung so eng zu verzahnen. Das "editable" und der "Label" dienen doch bestimmt dazu, ein Eingabeformular für das entsprechende Datenobjekt zu erstellen, haben aber nichts direkt mit der Definition zu tun.

Ich würde da dann lieber sowas machen:

Code: Alles auswählen

FooForm = ModelForm(FooModel, readonly='bar,baz', exclude='foo')
Oder das andere Extrem der totalen Verzahnung:

Code: Alles auswählen

class FooModel(Model):
    bar = UnicodeField(length=255, label="Bar", visible_for="Admin", editable_for="User,Guest")
Ist dir das zu viel Information in einer Zeile, erfinde eine Namenskonvention, wie zum Beispiel:

Code: Alles auswählen

class FooModel(Model):
    bar = ...
    bar_visibility = admin_group
    bar_changeability = user_group + guest_group
    bar_validator = lambda value: len(value) < 255
Das ginge zwar auch alles in Java, ist in Python aber viel leichtgewichtiger und flexibler und daher IMHO der bessere Weg. Entscheidend ist, das sagst du ja auch, wie es sich nachher liest.

Übrigens, "type" ist ein schlechter Name, da es schon eine gleichnamige Systemfunktion gibt, die man sich in einer Funktion u.U. überschreibt.

Stefan

Verfasst: Mittwoch 5. November 2008, 19:08
von Y0Gi
Ich denke nicht, dass der Name eines Keyword-Arguments irgendwas außerhalb der Callable-Definition überschreibt.

Verfasst: Mittwoch 5. November 2008, 20:56
von Qubit
DatenMetzgerX hat geschrieben: Emfpinde ich einfach als unesthetisch ;)

Code: Alles auswählen

  #schöner
  @editable(label="Titel")
  titel = Field(type=Unicode(255))

  #weniger toll
  titel = Field(type=Unicode(255))
  titel.label = "Titel" 
  titel.editable = true

Was sich aber recht einfach implementieren lässt, ist

Code: Alles auswählen

@Editable(label='Titel')
def create_Field(args): return Editable.Field
    
titel = create_Field(typ='unicode(255)')

Verfasst: Mittwoch 5. November 2008, 21:03
von lunar
Y0Gi hat geschrieben:Ich denke nicht, dass der Name eines Keyword-Arguments irgendwas außerhalb der Callable-Definition überschreibt.
Der Name überschreibt das Builtin im Funktionskörper, ob das ein Problem ist, muss man selbst entscheiden. "type" gehört jetzt imho nicht zu den Builtins, die man oft verwendet, insofern sehe ich da per se kein Problem. Ein Argument namens "open" wäre da problematischer ....

Verfasst: Mittwoch 5. November 2008, 21:21
von Leonidas
Qubit hat geschrieben:Was sich aber recht einfach implementieren lässt, ist

Code: Alles auswählen

@Editable(label='Titel')
def create_Field(args): return Editable.Field
    
titel = create_Field(typ='unicode(255)')
Also wenn ich sowas in fremden Code sehen würde, müsste ich mir erstmal klar machen, ob der Autor das ernst meint oder ob das nur ein Witz ist.

Zum Überschreiben von Builtins: Grundsätzlich kein Problem, aber spätestens wenn es jemand erweitert und auf ein überschriebenes Builtin zugreift kann das zu seltsamen Problemen führen. Ich für meinen Teil versuche es soweit möglich zu vermeiden.

Verfasst: Mittwoch 5. November 2008, 22:51
von Qubit
Leonidas hat geschrieben:
Qubit hat geschrieben:Was sich aber recht einfach implementieren lässt, ist

Code: Alles auswählen

@Editable(label='Titel')
def create_Field(args): return Editable.Field
    
titel = create_Field(typ='unicode(255)')
Also wenn ich sowas in fremden Code sehen würde, müsste ich mir erstmal klar machen, ob der Autor das ernst meint oder ob das nur ein Witz ist.
Hehe.., die Sprache soll doch "Fun" bringen ;-)
No magic..

Code: Alles auswählen

def Field_titel(typ):
    return 'Titel Inhalt fuer '+typ


class editable_Field:
    def __init__(self,args):
        self.args = args
        self.args['editable'] = True

class Editable:
    def __init__(self,**args):
        self.args = args
    def __call__(self,func):
        return func(self,self.args)
    def Field(self,typ):
        self.args['typ'] = typ
        labels = {
            'Titel': Field_titel
            }
        selected_field_type = labels.get(self.args['label'],None)
        if selected_field_type: self.args['content'] = selected_field_type(typ)
        else: raise Exception, 'Wrong field type'
        return editable_Field(self.args)

@Editable(label='Titel')
def create_Field(self,args): return self.Field

>>> 
>>> titel = create_Field(typ='unicode(255)')
>>> titel
<__main__.editable_Field instance at 0x0143C2B0>
>>> titel.__dict__
{'args': {'content': 'Titel Inhalt fuer unicode(255)', 'editable': True, 'typ': 'unicode(255)', 'label': 'Titel'}}
>>>