2014-10-31 21 views
6

Sto provando ad implementare il campo Select2 in una delle mie viste a flacone. Fondamentalmente voglio lo stesso campo select2 nella vista della mia applicazione di flask (non una view del modello admin di flask) come nel modello di Flask-admin creare viste. Attualmente la mia soluzione è stata QuerySelectField da wtforms che sembra qualcosa di simileImplementazione campo Select2 in flask/flask-admin

class TestForm(Form): 
    name= QuerySelectField(query_factory=lambda: models.User.query.all()) 

Questo mi permette di caricare e selezionare tutti i dati di cui ho bisogno, ma non fornisce casella di ricerca select2 ecc Attualmente tutto quello che ho trovato è Select2Field e Select2Widget da flask/admin/form/fields e flask/admin/form/widgets come in questo post https://stackoverflow.com/questions/24644960/how-to-steal-flask-admin-tag-form-field e anche select2 documentation a http://ivaynberg.github.io/select2/ Da intendersi potrebbero essere riutilizzabili, il che significa che non sono necessari altri widget personalizzati, Campi personalizzati.

Sarebbe grato se qualcuno potesse fornire ulteriori informazioni sull'implementazione del campo select2 nell'applicazione flask (comprese viste, modelli, file di moduli e come "connettere" correttamente con i file js e css necessari, anche come caricare il campo con il modello di database che mi serve).

risposta

2

questo ha funzionato per me:

... 
from wtforms.ext.sqlalchemy.fields import QuerySelectField 
from flask_admin.form.widgets import Select2Widget 
... 

class TestForm(Form): 
    name= QuerySelectField(query_factory=lambda: models.User.query.all(), 
          widget=Select2Widget()) 

E nel modello:

{% extends "admin/master.html" %} 
{% import 'admin/lib.html' as lib with context %} 

{% block head %} 
    {{ super() }} 
    {{ lib.form_css() }} 
{% endblock %} 

{% block body %} 
... 
{% endblock %} 

{% block tail %} 
    {{ super() }} 
    {{ lib.form_js() }} 
{% endblock %} 

posso provare a mettere insieme un esempio di lavoro minimo, se necessario.

+0

sto lottando con questo. Puoi per favore fare un esempio di lavoro minimo? –

+0

@glebocog È passato un po 'di tempo da quando l'ho usato ... se trovo il tempo che proverò, non posso prometterlo al momento. – PiQuer

0

Recentemente ho implementato un campo "tag" nel front-end di un'applicazione Flask, utilizzando Select2 e WTForms. Ho scritto un'applicazione di esempio, dimostrando come ho ottenuto lavorando (il codice della vista per popolare le opzioni di selezione, e per il salvataggio in modo dinamico nuove opzioni, è dove la maggior parte del lavoro avviene):

https://github.com/Jaza/flasktaggingtest

Si può vedere una demo di questa applicazione in:

https://flasktaggingtest.herokuapp.com/

No AJAX completamento automatico nel mio campione (solo popola il campo di selezione con tutte le etichette disponibili, durante l'inizializzazione del modulo). Oltre a questo, dovrebbe essere tutto ciò che in genere vorresti per un widget di tagging nelle tue viste/template Flask.

1

Avevo un requisito simile e ho messo insieme un esempio minimo.

Nota seguente:

Classe TestView definisce tre vie aeree; una vista get, una vista post e una vista di ricerca Ajax.

La funzione get_loader_by_name prende un nome stringa e restituisce un QueryAjaxModelLoader. Questa funzione è utilizzata sia nella chiamata di ricerca Ajax che nelle definizioni di campo TestForm.

Il testo visualizzato nei widget Select2 è il valore restituito dal metodo __unicode__ del modello utente.

ho usato Faker per generare i dati degli utenti campione.

File app.py:

from flask import Flask, render_template, url_for, request, abort, json, Response 
from flask.ext.admin import Admin, BaseView, expose, babel 
from flask.ext.admin.contrib.sqla.ajax import QueryAjaxModelLoader 
from flask.ext.admin.model.fields import AjaxSelectField, AjaxSelectMultipleField 
from flask.ext.sqlalchemy import SQLAlchemy 
from wtforms import Form 
from faker import Factory 

app = Flask(__name__) 
app.config['DEBUG'] = True 
app.config['SECRET_KEY'] = 'super-secret' 

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:' 
app.config['SQLALCHEMY_ECHO'] = True 
db = SQLAlchemy(app) 

try: 
    from flask_debugtoolbar import DebugToolbarExtension 
    DebugToolbarExtension(app) 
except: 
    pass 


class User(db.Model): 
    __tablename__ = 'users' 

    id = db.Column(db.Integer, primary_key=True) 

    first_name = db.Column(db.Unicode(length=255), nullable=False) 
    last_name = db.Column(db.Unicode(length=255), nullable=False) 
    email = db.Column(db.Unicode(length=254), nullable=False, unique=True) 

    def __unicode__(self): 
     return u"{first} {last}; {email}".format(first=self.first_name, last=self.last_name, email=self.email) 


def get_loader_by_name(name): 
    _dicts = { 
     'user': QueryAjaxModelLoader(
      'user', 
      db.session, User, 
      fields=['first_name', 'last_name', 'email'], 
      page_size=10, 
      placeholder="Select a user" 
     ) 
    } 
    return _dicts.get(name, None) 


class TestView(BaseView): 

    def __init__(self, name=None, category=None, 
       endpoint=None, url=None, 
       template='admin/index.html', 
       menu_class_name=None, 
       menu_icon_type=None, 
       menu_icon_value=None): 
     super(TestView, self).__init__(name or babel.lazy_gettext('Home'), 
              category, 
              endpoint or 'admin', 
              url or '/admin', 
              'static', 
              menu_class_name=menu_class_name, 
              menu_icon_type=menu_icon_type, 
              menu_icon_value=menu_icon_value) 
     self._template = template 

    @expose('/', methods=('GET',)) 
    def index_view(self): 
     _form = TestForm() 
     return self.render(self._template, form=_form) 

    @expose('/', methods=('POST',)) 
    def post_view(self): 
     pass 

    @expose('/ajax/lookup/') 
    def ajax_lookup(self): 
     name = request.args.get('name') 
     query = request.args.get('query') 
     offset = request.args.get('offset', type=int) 
     limit = request.args.get('limit', 10, type=int) 

     loader = get_loader_by_name(name) 

     if not loader: 
      abort(404) 

     data = [loader.format(m) for m in loader.get_list(query, offset, limit)] 
     return Response(json.dumps(data), mimetype='application/json') 

# Create admin and Test View 
admin = Admin(app, name='Admin', template_mode='bootstrap3') 
admin.add_view(TestView(template='test.html', name="Test", url='/test', endpoint='test')) 


class TestForm(Form): 

    single_user = AjaxSelectField(
     loader=get_loader_by_name('user') 
    ) 

    multiple_users = AjaxSelectMultipleField(
     loader=get_loader_by_name('user') 
    ) 


@app.route('/') 
def index(): 
    return render_template("index.html", link=url_for('test.index_view')) 


def build_db(): 

    db.drop_all() 
    db.create_all() 
    fake = Factory.create() 
    for index in range(0, 1000): 
     _first_name = fake.first_name() 
     _last_name = fake.last_name() 
     _user_db = User(
      first_name=_first_name, 
      last_name=_last_name, 
      email="{first}.{last}{index}@example.com".format(first=_first_name.lower(), last=_last_name.lower(), index=index) 
     ) 
     db.session.add(_user_db) 

    db.session.commit() 


@app.before_first_request 
def before_first_request(): 
    build_db() 


if __name__ == '__main__': 
    app.debug = True 
    app.run(port=5000, debug=True) 

File templates/index.html:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title>Test Select2</title> 
</head> 
<body> 
    <a href="{{ link }}">Go to the test form</a> 
</body> 
</html> 

file templates/test.html:

{% import 'admin/static.html' as admin_static with context %} 
{% import 'admin/lib.html' as lib with context %} 

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title>Test Select2</title> 
    <link href="{{ admin_static.url(filename='bootstrap/bootstrap3/css/bootstrap.min.css') }}" rel="stylesheet"> 
    <link href="{{ admin_static.url(filename='bootstrap/bootstrap3/css/bootstrap-theme.min.css') }}" rel="stylesheet"> 
    <link href="{{ admin_static.url(filename='admin/css/bootstrap3/admin.css') }}" rel="stylesheet"> 
    {{ lib.form_css() }} 
</head> 
<body> 

    <div class="container"> 
     <div class="row"> 
      <div class="col-sm-10 col-sm-offset-2"> 
       <form> 
        {{ lib.render_form_fields(form) }} 
       </form> 
      </div> 
     </div> 
    </div> 

    <script src="{{ admin_static.url(filename='vendor/jquery-2.1.1.min.js') }}" type="text/javascript"></script> 
    <script src="{{ admin_static.url(filename='bootstrap/bootstrap3/js/bootstrap.min.js') }}" type="text/javascript"></script> 
    <script src="{{ admin_static.url(filename='vendor/moment-2.8.4.min.js') }}" type="text/javascript"></script> 
    <script src="{{ admin_static.url(filename='vendor/select2/select2.min.js') }}" type="text/javascript"></script> 
    {{ lib.form_js() }} 

</body> 
</html>