2017-04-23 4 views
2

Nun, ich habe vor kurzem an flask-admin herangetreten und kann nicht herausfinden, wie ich dieses Problem lösen kann. Ich weiß, dass ich form_choices verwenden kann, um die möglichen Werte für ein Textfeld durch Angabe einer Liste von Tupeln zu beschränken. Wie auch immer, form_choices erlaubt nur jeweils einen Wert auszuwählen. Wie kann ich festlegen, dass ich in manchen Fällen eine durch Kommas getrennte Liste von Werten benötige?Mehrere Auswahlmöglichkeiten in flask-admin form_choices

ich diese Abhilfe versucht:

form_args = { 
    'FIELD': { 
     'render_kw': {"multiple": "multiple"}, 
    } 
} 

aber, obwohl eine Mehrfachauswahl Eingang erscheint tatsächlich auf der Webseite, wird nur der erste Wert gespeichert.

EIDT 05/13/2017

Durch ein wenig mit Kolben-admin Spielen fand ich zwei mögliche (Teil-) Lösung für meine Frage, die beide mit spezifischen Nachteilen.

1) Der erste befasst sich mit der Verwendung von Select2TagsField

from flask_admin.form.fields import Select2TagsField 
... 
form_extra_fields = { 
    'muri': Select2TagsField() 
} 

Mit dieser Methode ist es möglich, einfach für den normalen Texteingabe wählen Sie die Menü zu implementieren, obwohl derzeit Ich verstehe nicht, wie Entscheidungen zu übergeben Select2TagsField. Es funktioniert gut als eine Art multiple freie Texteingabe. Soweit ich verstehe, ist es jedoch nicht möglich, Select2TagsField und form_choices

2) Die zweite ist ein bisschen länger, aber es bietet mehr Kontrolle über Code (zumindest vermute ich). Noch es die Verwendung von form_choices impliziert, aber diesmal gepaart mit on_model_change

form_args = { 
    'FIELD': { 
     'render_kw': {"multiple": "multiple"}, 
    } 
} 
form_choices = {'FIELD': [ 
    ('1', 'M1'), ('2', 'M2'), ('3', 'M3'), ('4', 'M4') 
]} 
... 
def on_model_change(self, form, model, is_created): 
    if len(form.FIELD.raw_data) > 1: 
     model.FIELD = ','.join(form.FIELD.raw_data) 

Diese Lösung trotz der ersteren ermöglicht Entscheidungen abzubilden und funktioniert gut, wenn Daten an das Modell hinzufügen, aber es hat einige in der Bearbeitung gibt Probleme. Jedes Mal, wenn ich den Bearbeitungsdialog öffne, ist das FELD leer. Wenn ich mir die Daten ansehe (mit on_form_prefill durch Drucken form.FIELD.data) bekomme ich eine Komma-getrennte Zeichenfolge im Terminal, aber nichts erscheint im entsprechenden Auswahlfeld auf der Webseite.

Antwort

2

Damit dieser Ansatz funktioniert, müssten Sie eine Spalte verwenden, die eine Liste von Elementen speichern kann. Zumindest mit sqlite ist dies mit Flask-Admin nicht möglich. Es wäre jedoch besser, wenn Sie Ihre Auswahlmöglichkeiten in einem separaten Datenmodell speichern und Einschränkungen verwenden, um die beiden Modelle zu verknüpfen. Sehen Sie ein Arbeitsbeispiel hier.

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy 
from flask_admin import Admin 
from flask_admin.contrib.sqla import ModelView 


app = Flask(__name__) 
app.config['SECRET_KEY'] = '8e12c91677b3b3df266a770b22c82f2f' 
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:' 
db = SQLAlchemy(app) 
admin = Admin(app) 


item_tag_relation = db.Table('item_tag_relation', 
    db.Column('item_id', db.Integer, db.ForeignKey('item.id')), 
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')) 
) 


class Item(db.Model): 
    id = db.Column(db.Integer(), primary_key=True) 
    name = db.Column(db.String()) 
    tags = db.relationship("Tag", 
           secondary=item_tag_relation, 
           backref="items") 

    def __repr__(self): 
     return self.name 


class Tag(db.Model): 
    id = db.Column(db.Integer(), primary_key=True) 
    name = db.Column(db.String()) 

    def __repr__(self): 
     return self.name 


class ItemModelView(ModelView): 
    pass 


db.create_all() 
admin.add_view(ItemModelView(Item, db.session)) 
admin.add_view(ModelView(Tag, db.session)) 

if __name__ == '__main__': 
    app.run(debug=True) 
+0

dank MrLeeh Modelview für Sie tun (die richtige Antwort, nein Zweifel). Ich weiß, dass der vorgeschlagene Ansatz in der Tat nicht sehr orthodox ist, aber da in meinem Modell viele Fälle wie der oben erwähnte vorkommen (Fälle, die sehr selten verwendet werden müssen), habe ich mich gefragt, ob es einige Methoden gibt, dieselben zu erben Verhalten einer N: M-Beziehung ohne Alternieren des Modells. Ich dachte an eine durch Komma getrennte String-Liste, aber ich weiß nicht, wie ich dies mit Flask-Admin angeben soll – Pankus

2

Vielleicht ist das schon veraltet, aber ich schaffte es zu ändern und es mit einem Multiple-Choice-Array-Feld von Postgres zu arbeiten. Damit es funktioniert ich Select2Field erweitert zu wissen, wie mit der Liste beschäftigen:

class MultipleSelect2Field(Select2Field): 
    """Extends select2 field to make it work with postgresql arrays and using choices. 

    It is far from perfect and it should be tweaked it a bit more. 
    """ 

    def iter_choices(self): 
     """Iterate over choices especially to check if one of the values is selected.""" 
     if self.allow_blank: 
      yield (u'__None', self.blank_text, self.data is None) 

     for value, label in self.choices: 
      yield (value, label, self.coerce(value) in self.data) 

    def process_data(self, value): 
     """This is called when you create the form with existing data.""" 
     if value is None: 
      self.data = [] 
     else: 
      try: 
       self.data = [self.coerce(value) for value in value] 
      except (ValueError, TypeError): 
       self.data = [] 

    def process_formdata(self, valuelist): 
     """Process posted data.""" 
     if not valuelist: 
      return 

     if valuelist[0] == '__None': 
      self.data = [] 
     else: 
      try: 
       self.data = [self.coerce(value) for value in valuelist] 
      except ValueError: 
       raise ValueError(self.gettext(u'Invalid Choice: could not coerce')) 

    def pre_validate(self, form): 
     """Validate sent keys to make sure user don't post data that is not a valid choice.""" 
     sent_data = set(self.data) 
     valid_data = {k for k, _ in self.choices} 
     invalid_keys = sent_data - valid_data 
     if invalid_keys: 
      raise ValueError('These values are invalid {}'.format(','.join(invalid_keys))) 

und es zu verwenden, um dies auf dem

class SomeView(ModelView): 
    form_args = dict(FIELD=dict(render_kw=dict(multiple="multiple"), choices=CHOICES_TUPLE)) 
    form_overrides = dict(FIELD=MultipleSelect2Field) 
Verwandte Themen