Implementing select2 option in admin jar / jar

I am trying to implement a Select2 field in one of my flash representations. Basically, I want to have the same select2 field in my view of the flask application (and not in the form of a flash admin), since the views are created in the Flask-admin model. My current solution was QuerySelectField from wtforms, which looks something like this.

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

This allows me to load and select all the data I need, but it does not provide a select2 select box, etc. Currently, all I found is Select2Field and Select2Widget from the flask / admin / form / fields and flask / admin / form / widgets similarly in this post https://stackoverflow.com/questions/24644960/how-to-steal -flask-admin-tag-form-field , and also select2 documentation at http://ivaynberg.imtqy.com/select2/ As far as I understand, they can be reused, that is, there is no need for other custom widgets, custom fields.

It would be grateful if someone could provide additional information about the implementation of the select2 field in a flash application (including views, templates, form files and how to "connect" with the necessary js and css files, as well as how to load the field using me need a database model.

+7
source share
4 answers

This worked for 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()) 

And in your template:

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

I can try to put together a minimal working example if necessary.

+3
source

I had a similar requirement and I put together a minimal example.

Please note the following:

The TestView class defines three routes; view get, view post and view Ajax.

The get_loader_by_name function takes a string name and returns a QueryAjaxModelLoader . This function is used both in an Ajax search call and in TestForm field TestForm .

The text displayed in Select2 widgets is the value returned by the __unicode__ custom model __unicode__ .

I used Faker to create a sample user data.

App.py file:

 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> 

July 2018 Update

Added stand-alone Flask extension - Flask-Select2 - WIP on Github.

+3
source

I recently implemented a β€œtags” field in the Flask application interface using Select2 and WTForms. I wrote an example application, demonstrating how I work it (viewing code to fill in the selection options and dynamically save new parameters - this is where most of the work is):

https://github.com/Jaza/flasktaggingtest

You can see a demo of this application at:

https://flasktaggingtest.herokuapp.com/

In my example, there is no AJAX autocomplete (it just fills the selection box with all available tags when initializing the form). Other than that, there should be everything you would normally want for a widget with labels in your Flask views / templates.

+1
source

The other answers do not seem to work anymore. What I did to make it work:

On the backend:

  from wtforms.ext.sqlalchemy.fields import QuerySelectField, QuerySelectMultipleField ... users = users = QuerySelectMultipleField('users', query_factory=lambda: User.query.order_by(User.fullname).all(), get_label=lambda u: u.fullname, get_pk=lambda u: u.id) 

Then in the interface:

  $("#users").attr("multiple", "multiple").select2(); 

You need to manually add css and js for select2.

0
source

Source: https://habr.com/ru/post/977569/


All Articles