Commit 0d73f9a2 authored by Serge S. Koval's avatar Serge S. Koval

Unit tests

parent 890863fe
from sqlalchemy import or_
from flask.ext.admin._compat import as_unicode
from flask.ext.admin.model.ajax import AjaxModelLoader, DEFAULT_PAGE_SIZE
class QueryAjaxModelLoader(AjaxModelLoader):
def __init__(self, name, session, model, fields):
"""
Constructor.
:param fields:
Fields to run query against
"""
super(QueryAjaxModelLoader, self).__init__(name)
self.session = session
self.model = model
self.fields = fields
primary_keys = model._sa_class_manager.mapper.primary_key
if len(primary_keys) > 1:
raise NotImplemented('Flask-Admin does not support multi-pk AJAX model loading.')
self.pk = primary_keys[0].name
def format(self, model):
if not model:
return None
return (getattr(model, self.pk), as_unicode(model))
def get_one(self, pk):
return self.session.query(self.model).get(pk)
def get_list(self, term, offset=0, limit=DEFAULT_PAGE_SIZE):
query = self.session.query(self.model)
filters = (field.like('%%%s%%' % term) for field in self.fields)
query = query.filter(or_(*filters))
return query.offset(offset).limit(limit).all()
DEFAULT_PAGE_SIZE = 10
class AjaxModelLoader(object):
"""
Ajax related model loader. Override this to implement custom loading behavior.
"""
def __init__(self, name):
"""
Constructor.
:param name:
Field name
"""
self.name = name
def format(self, model):
"""
Return (id, name) tuple from the model.
"""
raise NotImplemented()
def get_one(self, pk):
"""
Find model by its primary key.
:param pk:
Primary key value
"""
raise NotImplemented()
def get_list(self, query, offset=0, limit=DEFAULT_PAGE_SIZE):
"""
Return models that match `query`.
:param view:
Administrative view.
:param query:
Query string
:param offset:
Offset
:param limit:
Limit
"""
raise NotImplemented()
...@@ -1213,5 +1213,5 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -1213,5 +1213,5 @@ class BaseModelView(BaseView, ActionsMixin):
if not loader: if not loader:
abort(404) abort(404)
data = [loader.format(m) for m in loader.get_models(query, offset, limit)] data = [loader.format(m) for m in loader.get_list(query, offset, limit)]
return Response(json.dumps(data), mimetype='application/json') return Response(json.dumps(data), mimetype='application/json')
...@@ -8,6 +8,7 @@ def setup(): ...@@ -8,6 +8,7 @@ def setup():
app.config['SECRET_KEY'] = '1' app.config['SECRET_KEY'] = '1'
app.config['CSRF_ENABLED'] = False app.config['CSRF_ENABLED'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'
#app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app) db = SQLAlchemy(app)
admin = Admin(app) admin = Admin(app)
......
...@@ -3,6 +3,7 @@ from nose.tools import eq_, ok_, raises ...@@ -3,6 +3,7 @@ from nose.tools import eq_, ok_, raises
from wtforms import fields from wtforms import fields
from flask.ext.admin import form from flask.ext.admin import form
from flask.ext.admin._compat import as_unicode
from flask.ext.admin._compat import iteritems from flask.ext.admin._compat import iteritems
from flask.ext.admin.contrib.sqla import ModelView from flask.ext.admin.contrib.sqla import ModelView
...@@ -37,6 +38,9 @@ def create_models(db): ...@@ -37,6 +38,9 @@ def create_models(db):
bool_field = db.Column(db.Boolean) bool_field = db.Column(db.Boolean)
enum_field = db.Column(db.Enum('model1_v1', 'model1_v1'), nullable=True) enum_field = db.Column(db.Enum('model1_v1', 'model1_v1'), nullable=True)
def __str__(self):
return self.test1
class Model2(db.Model): class Model2(db.Model):
def __init__(self, string_field=None, int_field=None, bool_field=None, model1=None): def __init__(self, string_field=None, int_field=None, bool_field=None, model1=None):
self.string_field = string_field self.string_field = string_field
...@@ -675,3 +679,62 @@ def test_custom_form_base(): ...@@ -675,3 +679,62 @@ def test_custom_form_base():
create_form = view.create_form() create_form = view.create_form()
ok_(isinstance(create_form, TestForm)) ok_(isinstance(create_form, TestForm))
def test_ajax_fk():
app, db, admin = setup()
Model1, Model2 = create_models(db)
view = CustomModelView(
Model2, db.session,
url='view',
form_ajax_refs={
'model1': ('test1', 'test2')
}
)
admin.add_view(view)
ok_(u'model1' in view._form_ajax_refs)
model = Model1(u'first')
db.session.add_all([model, Model1(u'foo', u'bar')])
db.session.commit()
# Check loader
loader = view._form_ajax_refs[u'model1']
mdl = loader.get_one(model.id)
eq_(mdl.test1, model.test1)
items = loader.get_list(u'fir')
eq_(len(items), 1)
eq_(items[0].id, model.id)
items = loader.get_list(u'bar')
eq_(len(items), 1)
eq_(items[0].test1, u'foo')
# Check form generation
form = view.create_form()
eq_(form.model1.__class__.__name__, u'AjaxSelectField')
with app.test_request_context('/admin/view/'):
ok_(u'value="null"' in form.model1())
form.model1.data = model
ok_(u'value="[1, "first"]"' in form.model1())
# Check querying
client = app.test_client()
req = client.get(u'/admin/view/ajax/lookup/?name=model1&query=foo')
eq_(req.data, u'[[2, "foo"]]')
# Check submitting
req = client.post('/admin/view/new/', data={u'model1': as_unicode(model.id)})
mdl = db.session.query(Model2).first()
ok_(mdl is not None)
ok_(mdl.model1 is not None)
eq_(mdl.model1.id, model.id)
eq_(mdl.model1.test1, u'first')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment