Seite 1 von 2
Flask Macro - Selectbox rendern
Verfasst: Donnerstag 17. Dezember 2015, 22:13
von meego
Wie bringe ich das Optionsfeld (disabled) im oberen <select> an die erste Stelle des unteren <select>?
http://pastie.org/private/ua9cmxmywdt2rcgdq8cjq
Re: Flask Macro - Selectbox rendern
Verfasst: Sonntag 20. Dezember 2015, 15:26
von noisefloor
Hallo,
ohne das du noch das Macro zeigst kommt hier wohl keiner weiter...
Gruß, noisefloor
Re: Flask Macro - Selectbox rendern
Verfasst: Montag 21. Dezember 2015, 12:33
von meego
Hallo Noisefloor
Die Definition vom Macro (_formhelpers.html) steht oben im paste. Meinst du den Aufruf?
Wäre dann einfach:
LG
Re: Flask Macro - Selectbox rendern
Verfasst: Montag 21. Dezember 2015, 12:56
von BlackJack
Das <select> wird ja durch die Umwandlung von `field` in eine Zeichenkette erzeugt. Wenn Du da etwas anders haben willst, dann musst Du auch *dort* ansetzen. Also was ist `field` für ein Datentyp und wie kann man die Umwandlung da beeinflussen, falls man das überhaupt kann. Wenn man das nicht kann, dann musst Du das durch eine Funktion oder ein Makro ersetzen das `field` so in HTML umwandelt wie Du das gerne hättest.
Re: Flask Macro - Selectbox rendern
Verfasst: Montag 21. Dezember 2015, 13:00
von noisefloor
Hallo,
Die Definition vom Macro (_formhelpers.html) steht oben im paste. Meinst du den Aufruf?
Nee - war ein Denkfehler meinerseits, sorry.
BlackJack es ja schon gesagt: das Makro ist im Prinzip zu "high level". Wenn du die Optionen des Select-Fields per Schleife im Makro erzeugst, dann ist auch das setzen der nicht-wählbaren Default-Option nicht das Problem.
Gruß, noisefloor
Re: Flask Macro - Selectbox rendern
Verfasst: Montag 21. Dezember 2015, 15:57
von meego
Ich verstehe da gerade nur Bahnhof. Das ich das obere Select idealerweise irgendwie beim Field als Argument übergeben müsste ist mir klar.
Das WTForm field ist:
Code: Alles auswählen
country = QuerySelectField('Country', query_factory=lambda: Country.query, get_label=lambda x: x.name)
Es stammt aus dem Paket:
wtforms.ext.sqlalchemy.fields
Re: Flask Macro - Selectbox rendern
Verfasst: Montag 21. Dezember 2015, 16:32
von BlackJack
@meego: Da würde man dann wohl diesen Typ und das zugeordnete widget entsprechend ableiten und modifizieren müssen damit das dann entsprechend gerendert wird. Das `Field` müsste bei `iter_choices()` diese spezielle Option als erstes liefern und das Widget müsste in seiner `render_option()`-Methode dieses erste spezielle Feld mit dem `disabled`-HTML-Attribut rendern.
Re: Flask Macro - Selectbox rendern
Verfasst: Montag 21. Dezember 2015, 17:01
von noisefloor
Hallo,
@meego: vom Prinzip her so (das ist kein echter Jinja2 Code):
Code: Alles auswählen
<select>
<option value="" disabled selected>Choose an option</option>
{% for field in fields %}
<option value="{{ field.value }}">{{ field.name }}</option>
{% endfor %}
</select>
Gruß, noisefloor
Re: Flask Macro - Selectbox rendern
Verfasst: Montag 21. Dezember 2015, 17:52
von meego
@blackjack: Over my head.
@noisefloor: Folgendes funktioniert nicht:
Code: Alles auswählen
{% macro render_selectfield(field) %}
<div class="input-field col s6">
<select>
<option value="" disabled selected>{{ _('Wähle deine Option') }}</option>
{% for f in field %}
<option value="{{ f.value }}">{{ f.name }}</option>
{% endfor %}
</select>
</div>
{% endmacro %}
Resultat:
Habe ich einen Fehler drin?
Re: Flask Macro - Selectbox rendern
Verfasst: Montag 21. Dezember 2015, 18:12
von noisefloor
Hallo,
Habe ich einen Fehler drin?
Natürlich, sonst würde es ja funktionieren
Ob `f.value` und `f.name` bei dir richtig ist weiß niemand außer dir, weil wir den restlichen Code nicht kennen. Das musst du halt ggf. noch anpassen, je nach dem, was in `field` so "drin" ist.
Gruß, noisefloor
Re: Flask Macro - Selectbox rendern
Verfasst: Montag 21. Dezember 2015, 20:42
von meego
Hallo Noisy
Das WTForm?:
Code: Alles auswählen
country = QuerySelectField('Country', query_factory=lambda: Country.query, get_label=lambda x: x.name)
Oder das Modell?:
Code: Alles auswählen
class Country(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
Da wäre das Attribut .name eigentlich vorhanden.
Re: Flask Macro - Selectbox rendern
Verfasst: Montag 21. Dezember 2015, 21:05
von noisefloor
Hallo,
ich habe zwar früher auch mal WTForms und SQLAlchemy benutzt - aber nie so, mit dem dynamischen befüllen von WTForms Feldern aus SA (und, das muss ich dann an dieser Stelle doch mal sagen: jetzt weiß ich auch wieder, warum ich heute Django nehme

).
Letzte Idee von mir: auf der Konsole debuggen bzw. inspizieren. Also alles importieren, und mal in die Form-Klasse reinschauen bzw. schauen, was hinter den Attributen des Klasse so für Inhalt steckt.
Gruß, noisefloor
Re: Flask Macro - Selectbox rendern
Verfasst: Dienstag 22. Dezember 2015, 12:55
von Sirius3
@meego: WTForms ist ja ganz schön verschachtelt. Als erstes brauchst Du ein neues Select-Widget, dann ein QuerySelectField, das auf dieses Widget verweist:
Code: Alles auswählen
from wtforms import widgets
class SelectWithChooseOption(widgets.Select):
def __call__(self, field, **kwargs):
kwargs.setdefault('id', field.id)
if self.multiple:
kwargs['multiple'] = True
html = ['<select %s>' % html_params(name=field.name, **kwargs)]
any_selected = False
for val, label, selected in field.iter_choices():
html.append(self.render_option(val, label, selected))
any_selected |= selected
html.insert(1, self.render_option('', 'Choose your option', selected=not any_selected, disabled=True)
html.append('</select>')
return HTMLString(''.join(html))
class QuerySelectFieldWithChooseOption(QuerySelectField):
widget = SelectWithChooseOption()
Re: Flask Macro - Selectbox rendern
Verfasst: Dienstag 22. Dezember 2015, 15:57
von meego
Huch, Sirius, das ist aber kompliziert. Und das ist tatsächlich die einfachste Art und Weise zum Ergebnis zu kommen?
@noisefloor: Django habe ich mir auch angesehen, das Tutorial war aber nicht gerade Newbiefreundlich und didaktisch eher verwirrend, immer vom Spezialfall zur normalen Anwendung. Jetzt würde ich vielleicht schon etwas mehr davon verstehen.
Re: Flask Macro - Selectbox rendern
Verfasst: Dienstag 22. Dezember 2015, 16:13
von BlackJack
@meego: Den ”einfacheren” Weg hatte ich ja schon angerissen, da muss man dann aber sowohl das `Field` als auch das passende `Widget` ableiten. Dafür muss man nicht den grossteil der `__call__()`-Methode vom originalen `Select` abschreiben.
Re: Flask Macro - Selectbox rendern
Verfasst: Dienstag 22. Dezember 2015, 16:56
von noisefloor
Hallo,
das ist aber kompliziert. Und das ist tatsächlich die einfachste Art und Weise zum Ergebnis zu kommen?
Auf anderem Wege habe ich das zumindest nicht geschafft. Und die Lösung von Sirius findet man so oder in sehr ähnlicher Form auch in diversen Threads bei SO.
Und kompliziert ist es für doch doch nicht wirklich - Code per C&P übernehmen und gut ist
Gruß, noisefloor
Re: Flask Macro - Selectbox rendern
Verfasst: Dienstag 22. Dezember 2015, 17:18
von meego
@Blackjack, ich weiss nicht einmal, wozu die __call__ methode gut ist. Meinst du, mit einem Programmier-Profi zu sprechen?
@Noisefloor: C & P mache ich nur ungern, wenn ich den Code selber nicht verstehe. Was ist SO? Eine andere Alternative wäre einfach die
normale Selectbox rendern, zumal das ganze JS-zeug etwas langsam ist.
Re: Flask Macro - Selectbox rendern
Verfasst: Dienstag 22. Dezember 2015, 17:38
von BlackJack
@meego: Was die `__call__()`-Methode generell macht kann man in der Python-Dokumentation nachlesen und was sie bei WTForms semantisch macht, sollte man dort in der Dokumentation nachlesen können. Die wandelt das `Field` in HTML-Quelltext um. Wenn man also beeinflussen will *wie* das passiert, dann muss man sich die halt anschauen und zum Beispiel kopieren und den eigenen Wünschen anpassen. Alternativ kann man schauen was die so von sich und anderen Objekten verwendet und dort die entsprechenden Methoden überschreiben/verändern.
SO =
StackOverflow.
Re: Flask Macro - Selectbox rendern
Verfasst: Dienstag 22. Dezember 2015, 19:53
von noisefloor
Hallo,
C & P mache ich nur ungern, wenn ich den Code selber nicht verstehe.
Sagen wir mal so: die meisten von uns - und da schließe ich mich explizit mit ein - werden den Code der Module, die wir einsetzen, nicht verstehen

Bei WTForms z.B. leitest du dir auch eigne Klassen ab und zu wissen, was die Basisklasse macht. Und warum da die Attribute so definiert werden, wie es halt gemacht wird, ist den meisten wahrscheinlich auch nicht klar.
Die Alternative zur Lösung von Sirius wäre noch, dass du den "Choose an Option" Eintrag regulär einfügst und dann auf der Webseite per JavaScript deaktivierst. Wobei das eigene Widget IMHO deutlich eleganter ist.
Und nochmal kurz zu Django: in einer meiner Apps leite ich eine Form aus einem Model für die DB ab. Beim Rendern der Form im Template ist der 1. automatisch `-------`. Diese ist zwar auswählbar, allerdings validiert die Form nicht, wenn man diesen Eintrag wählt.
Ich habe früher ja auch Bottle + WTForms + SQLAlchemy eingesetzt. Was ich selber aber bei Django _wesentlich_ angenehmer finde ist, dass alles unter einer Haube ist und damit sehr gut integriert. Was nicht heißt, dass Django per se besser und alles andere keine Existenzberechtigung.
Gruß, noisefloor
Re: Flask Macro - Selectbox rendern
Verfasst: Donnerstag 24. Dezember 2015, 00:59
von meego
Gerade mal schnell ausprobiert. Sieht aus wie im Widgetsbeispiel in der Doku, was ist das Problem?:
Code: Alles auswählen
Traceback (most recent call last):
File "/../forms.py", line 76
html.append('</select>')
@Blackjack: Danke, werde mir wtforms mal etwas genauer ansehen.
@Noisy: Ein '-------' finde ich aber jetzt aber etwas schräg (wenn man das nicht ändern kann). Ja, ich habe mir auch schon die Sinnfrage gestellt, weil man ja letztlich doch alle Erweiterungen benötigt (Migrationen, Admin, wtforms, alchemy, babel). Allerdings haben die selbst im Djangoforum gesagt, SQLalchemy würden sie lieber verwenden und irgendwie ist's bis jetzt einfach näher an der Pythonsyntax, also gerade als Newbie vielleicht besser zum lernen.