2014-10-31 2 views
6

Я пытаюсь реализовать поле Select2 в одном из своих представлений фляжек. В принципе, я хочу иметь такое же поле select2 в моем представлении приложения фляги (а не в виде флеш-админки), так как в модели Flask-admin создаются представления. В настоящее время мое решение было QuerySelectField от wtforms, который выглядит примерно такВставка выбора2 в фляге/фляж-админ

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

Это позволяет мне загружать и выбрать все нужные данные, но он не обеспечивает ВЫБ.2 окно поиска и т.д. В настоящее время все, что я нашел Select2Field и Select2Widget из flask/admin/form/fields и flask/admin/form/widgets аналогично в этом сообщении https://stackoverflow.com/questions/24644960/how-to-steal-flask-admin-tag-form-field, а также документацию select2 по адресу http://ivaynberg.github.io/select2/ Как я понимаю, они могут быть многоразовыми, то есть нет необходимости в других пользовательских виджетах, Настраиваемые поля.

Было бы благодарен, если кто-то может предоставить дополнительную информацию о реализации поля select2 в флеш-приложении (включая представления, шаблоны, файлы форм и правильное «соединение» с необходимыми js и css-файлами, а также как загрузить поле с помощью мне нужна модель базы данных).

ответ

2

Это работает для меня:

... 
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()) 

И в шаблоне:

{% 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 %} 

Я могу попытаться собрать минимальный рабочий пример, если это необходимо.

+0

Я борюсь с этим. Можете ли вы сделать этот минимальный рабочий пример? –

+0

@glebocog Прошло некоторое время с тех пор, как я использовал это ... если найду время, которое я попробую, не могу обещать в данный момент. – PiQuer

0

Недавно я внедрил поле «теги» в интерфейсе флеш-приложения, используя Select2 и WTForms. Я написал пример приложения, демонстрирующий, как я получил это работает (код вида для заселения выбора параметров, а также для динамического сохранения новых параметров, в котором большая часть работы происходит):

https://github.com/Jaza/flasktaggingtest

Вы можете увидеть демонстрационный это приложение на:

https://flasktaggingtest.herokuapp.com/

Нет AJAX автозаполнения в моем примере (это только заполнит поле выбора со всеми доступными тегами, при инициализации формы). Помимо этого, должно быть все, что вы обычно хотели бы для виджета с тегами в своих флагах/шаблонах.

1

У меня было аналогичное требование и составили минимальный пример.

Обратите внимание на следующее:

класса TestView определяет три маршрута; представление просмотра, просмотр сообщения и просмотр Ajax.

Функция get_loader_by_name берет имя строки и возвращает QueryAjaxModelLoader. Эта функция используется как в обращении вызова Ajax, так и в определениях полей TestForm.

Текст, отображаемый в виджетах Select2, является значением, возвращаемым методом __unicode__ модели пользователя.

Я использовал Faker для генерации выборочных пользовательских данных.

приложение.ру:

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) 

Файл шаблоны/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> 

Файл шаблоны/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>