Hier ist eine Möglichkeit, dies zu erreichen. Ich habe das komplette in sich abgeschlossene Beispiel auf Github, flask-admin-modal gestellt.
In diesem Beispiel ist das SQLite-Datenbankmodell ein Projekt mit den Attributen name (string) und cost (Integer), und wir aktualisieren den Kostenwert für ausgewählte Zeilen in der Flask-Admin-Listenansicht. Beachten Sie, dass die Datenbank mit zufälligen Daten gefüllt wird, wenn die Flask-Anwendung gestartet wird.
Hier ist das Modell:
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False, unique=True)
cost = db.Column(db.Integer(), nullable=False)
def __str__(self):
return unicode(self).encode('utf-8')
def __unicode__(self):
return "Name: {name}; Cost : {cost}".format(name=self.name, cost=self.cost)
definieren ein Formular mit einem ganzzahligen Kostenfeld, das die neuen Kosten übernimmt. Dieses Formular enthält auch ein verstecktes Feld, um die ausgewählten Zeilen-IDs zu verfolgen.
Überschreiben Sie die Listenvorlage für das Projektansichtsmodell. Wir tun dies, damit wir ein Bootstrap-Modal-Formular mit einer ID changeModel
innerhalb der {% block body %}
einfügen können, so dass wir zuerst {{ super() }}
aufrufen.
Wir fügen auch eine jQuery Dokument bereit Funktion, die das modale Formular zeigt, wenn eine Vorlage Variable (change_model
) als wahr ausgewertet wird. Dieselbe Variable wird im Modellkörper verwendet, um die change_form
anzuzeigen. Wir verwenden die flask-Admin lib Makros render_form, um das Formular in einem Bootstrap-Stil zu rendern.
Beachten Sie den Wert des Aktionsparameters in render_form
- es ist eine Route, die wir in unserer Projektansicht definieren, wo wir die Daten des Formulars verarbeiten können. Beachten Sie auch, dass die Schaltfläche "Schließen" durch einen Link ersetzt wurde, aber immer noch als Schaltfläche formatiert ist. Der Link ist die ursprüngliche URL (einschließlich Seiten- und Filterdetails), von der aus die Aktion initiiert wurde.
Die Projektsichtklasse muss das Verhalten der Batch-Aktionsmethode ändern und einige Routen definieren, die POST-Anforderungen akzeptieren.
@action('change_cost', 'Change Cost', 'Are you sure you want to change Cost for selected projects?')
def action_change_cost(self, ids):
url = get_redirect_target() or self.get_url('.index_view')
return redirect(url, code=307)
Statt Verarbeitung der ids direkt die Batch-Aktion die URL erhält, der die Aktion veröffentlicht, wird diese URL enthalten keine Seitenzahl und Filterdetails. Es führt dann eine Umleitung zurück zu der Listenansicht mit einer 307 durch. Dies stellt sicher, dass die ausgewählten Zeilen-IDs in dem Hauptteil mitgerissen werden, ebenso wie die Tatsache, dass es eine POST-Anfrage war.
Definieren Sie eine POST-Route, um diese Weiterleitung zu verarbeiten, erhalten Sie die IDs und URL aus dem Anfragetext, Instanz a ChangeForm
, legen Sie das ausgeblendete Formularfeld ids
auf eine codierte Liste der IDs. Fügen Sie den Vorlagenargumenten die Variablen url
, change_form
und change_model
hinzu, und rendern Sie dann die Listenansicht erneut - dieses Mal wird das modale Popup-Formular in der Ansicht angezeigt.
@expose('/', methods=['POST'])
def index(self):
if request.method == 'POST':
url = get_redirect_target() or self.get_url('.index_view')
ids = request.form.getlist('rowid')
joined_ids = ','.join(ids)
encoded_ids = base64.b64encode(joined_ids)
change_form = ChangeForm()
change_form.ids.data = encoded_ids
self._template_args['url'] = url
self._template_args['change_form'] = change_form
self._template_args['change_modal'] = True
return self.index_view()
eine POST-Route definieren die modale Form des Daten zu verarbeiten. Dies ist die Standardform/Datenbankverarbeitung, und wenn Sie fertig sind, leiten Sie zurück zur ursprünglichen URL, die die Aktion initiiert hat.
@expose('/update/', methods=['POST'])
def update_view(self):
if request.method == 'POST':
url = get_redirect_target() or self.get_url('.index_view')
change_form = ChangeForm(request.form)
if change_form.validate():
decoded_ids = base64.b64decode(change_form.ids.data)
ids = decoded_ids.split(',')
cost = change_form.cost.data
_update_mappings = [{'id': rowid, 'cost': cost} for rowid in ids]
db.session.bulk_update_mappings(Project, _update_mappings)
db.session.commit()
return redirect(url)
else:
# Form didn't validate
# todo need to display the error message in the pop-up
print change_form.errors
return redirect(url, code=307)
@pjcunningham Vielen Dank für Sie wirklich schöne Lösung. Ich habe es für meine Anwendung angepasst und es funktioniert super! Das einzige, was ich geändert habe, ist eine 'flash()' Nachricht anstelle von 'print change_form.errors', und ich habe' code = 307' danach entfernt. (Trotzdem sieht es immer noch wie eine Magie für mich aus.) –