Flask + Bootstrap: Problem mit has-error css in Form

Django, Flask, Bottle, WSGI, CGI…
Antworten
chrylag
User
Beiträge: 2
Registriert: Montag 18. Dezember 2017, 15:05

Montag 18. Dezember 2017, 18:55

Hallo,

ich bin derzeit dabei, eine kleine WebApp inklusive Userregistrierung mit Flask + Bootstrap + SQLAlchemy + wtforms zu schreiben.
Dazu nutze ich das render_field macro aus der wtforms Dokumentation.

Code: Alles auswählen

{% macro render_field(field) %}
  <dt>{{ field.label }}
  <dd>{{ field(**kwargs)|safe }}
  {% if field.errors %}
    <ul class=errors>
    {% for error in field.errors %}
      <li><b><font color="red">{{ error }}</font></b></li>
    {% endfor %}
    </ul>
  {% endif %}
  </dd>
{% endmacro %}
Das jinja2 Template für meine Registrierung sieht so aus:

Code: Alles auswählen

{% extends "base.html" %}

{% block body %}
<h1>Sign Up</h1>
{% from "includes/_formhelpers.html" import render_field %}

<form method="POST" action="">
		{{ form.hidden_tag() }}
	<div class="form-group {% if form.errors %} has-error {% endif %}"> // Methode eins, Rahmen ist um die gesamte Gruppe, nicht nur um die Input Klasse
		{{ render_field(form.name, class="form-control {% if form.errors %} has-error {% endif %}") }} // Methode zwei, Rahmen ist IMMER da
	</div>
	<div class="form-group">
		{{ render_field(form.vorname, class="form-control") }}
	</div>
	<div class="form-group">
		{{ render_field(form.username, class="form-control") }}
	</div>
	<div class="form-group">
		{{ render_field(form.email, class="form-control") }}
	</div>
	<div class="form-group">
		{{ render_field(form.password, class="form-control") }}
	</div>
	<div class="form-group">
		{{ render_field(form.confirm, class="form-control") }}
	</div>
	<p><input type="submit" class="btn btn-primary" value="Sign Up"></p>

</form>


{% endblock %}
Nun habe ich das Problem, dass mir sowohl die Border Dicke als auch die Border Farbe, wenn ein validator aus wtforms anschlägt, nicht so richtig zusagt.
Das sieht derzeit wir folgt aus:

[img][IMG]http://fs5.directupload.net/images/1712 ... d9pro7.png[/img][/img]

Ich habe dazu die Datei mycss.css angelegt, mit folgendem Inhalt:

Code: Alles auswählen

.has-error {
	border:solid red;
}
Und sie in meinem base Layout (von dem alle weiteren Templates erben) unter den Standard Bootstraps.css Dateien eingebunden.

Das ganze funktioniert aber nur so halb.
Wenn ich (in meinem Register-Template hinter dem "form-group" Tag

Code: Alles auswählen

{% if form.errors %} has-error {% endif %}
angebe, dann wird die ganze Gruppe (inklusive Label etc.) umrahmt. Das sieht dann so aus:

[img][IMG]http://fs1.directupload.net/images/1712 ... q8qz2r.png[/img][/img]

Also dachte ich mir, dass es sinnvoller wäre, das if-statement hinter die einzelnen form-controls zu schreiben.
Wenn ich dort allerdings o.g. if-statement hinter schreibe, wird die rote Border immer gerendert, auch wenn kein validator anschlägt.
Sozusagen so, als hätte ich - anstelle des if-statements - einfach nur ein "has-error" hinter das "form-control" gepackt.
Das ganze sieht so aus:

[img][IMG]http://fs5.directupload.net/images/1712 ... aw4u7i.png[/img][/img]

Prinzipiell ist das letzte Bild schon das, was ich mir vom Style her vorstelle.
Allerdings halt nur, wenn der validator ein Feld als "falsch" markiert. Nicht immer.

Was mache ich bei der ganzen Sache falsch? Warum funktioniert das if-statement bei der form-group class, nicht aber bei der form-control class?
Liegt es daran, dass die render_field funktion als argument nur ein field nimmt und kein weiteres, und ich hier versuche, ein weiteres zu übergeben?
Oder habe ich meine .css Datei falsch angelegt?

Vielen Dank im Voraus!
Sirius3
User
Beiträge: 8095
Registriert: Sonntag 21. Oktober 2012, 17:20

Dienstag 19. Dezember 2017, 09:07

@chrylag: Die doppelten geschweiften Klammern `{{ render_field(form.name, class="form-control {% if form.errors %} has-error {% endif %}") }}` umschließen schon Python-Code, in dem die Anführungszeichen einfache Strings sind. Das kannst Du auch einfach nachprüfen, indem Du schaust, welche Klasse Dein Feld wirklich hat: `class="form-control {% if form.errors %} has-error {% endif %}"`. Hier mußt Du also ein Python-if-else schreiben:

Code: Alles auswählen

render_field(form.name, class="form-control" + (" has-error" if form.errors else ""))
chrylag
User
Beiträge: 2
Registriert: Montag 18. Dezember 2017, 15:05

Mittwoch 20. Dezember 2017, 19:36

Super! Vielen Dank! :)
Hat auf Anhieb geklappt. Irgendwie stand ich da wohl auf dem Schlauch.

Aber mal noch eine andere Frage:
Ist es möglich, einen Validator auch "ausserhalb" der Form Validation zu aktivieren?

Ich bin aktuell am Login dran. Aktuell ist das so, dass sowohl Username als auch Passwort (logischerweise) den Validator InputRequired() haben.
Kann ich das irgendwie so bauen, dass der Passwort Validator (bzw. dessen Feld) auch mit einer Fehlermeldung ausgelöst wird, sollte das Passwort falsch sein?
Aktuell habe ich das als flash message, wäre mir aber lieber, wenn das PasswordField dann auch rot umrandet wäre und in dem Feld darunter (in dem auch steht "This field is required", wenn es leer gelassen wird) erscheint "invalid password" oder so.

Bin mir aber nicht ganz sicher, wie das zu realisieren wäre, da man die Validators ja beim erstellen des Forms angibt, nicht in der eigentlichen Login-Logik.

Also praktisch so, dass man irgendwie auf das validator label zugreifen kann.

(Ich bin mir nicht sicher, ob ich das jetzt einleuchtend erklärt habe :D )
Benutzeravatar
noisefloor
User
Beiträge: 2422
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Mittwoch 20. Dezember 2017, 20:35

Hallo,

grundsätzlich kannst du dir ja selber eine Validator schreiben, der die Korrektheit des Passworts prüft. Bzw. der Validator würde die passenden Funktionen aufrufen und je nach Rückgabewert einen ValidationError werfen.

Gruß, noisefloor
Antworten