Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
flask-admin
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Python-Dev
flask-admin
Commits
a51713a0
Commit
a51713a0
authored
Jun 09, 2015
by
Serge S. Koval
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed #897 - Ability to disable count queries and have back/fwd pager
parent
14dec4f5
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
135 additions
and
20 deletions
+135
-20
view.py
flask_admin/contrib/mongoengine/view.py
+2
-2
view.py
flask_admin/contrib/peewee/view.py
+2
-2
view.py
flask_admin/contrib/pymongo/view.py
+2
-2
view.py
flask_admin/contrib/sqla/view.py
+18
-9
base.py
flask_admin/model/base.py
+13
-3
lib.html
flask_admin/templates/bootstrap2/admin/lib.html
+25
-0
list.html
flask_admin/templates/bootstrap2/admin/model/list.html
+7
-1
lib.html
flask_admin/templates/bootstrap3/admin/lib.html
+23
-0
list.html
flask_admin/templates/bootstrap3/admin/model/list.html
+7
-1
test_basic.py
flask_admin/tests/mongoengine/test_basic.py
+17
-0
test_basic.py
flask_admin/tests/sqla/test_basic.py
+19
-0
No files found.
flask_admin/contrib/mongoengine/view.py
View file @
a51713a0
...
...
@@ -484,7 +484,7 @@ class ModelView(BaseModelView):
query
=
self
.
_search
(
query
,
search
)
# Get count
count
=
query
.
count
()
count
=
query
.
count
()
if
not
self
.
simple_list_pager
else
None
# Sorting
if
sort_column
:
...
...
@@ -592,7 +592,7 @@ class ModelView(BaseModelView):
return
False
else
:
self
.
after_model_delete
(
model
)
return
True
...
...
flask_admin/contrib/peewee/view.py
View file @
a51713a0
...
...
@@ -339,7 +339,7 @@ class ModelView(BaseModelView):
query
=
f
.
apply
(
query
,
f
.
clean
(
value
))
# Get count
count
=
query
.
count
()
count
=
query
.
count
()
if
not
self
.
simple_list_pager
else
None
# Apply sorting
if
sort_column
is
not
None
:
...
...
@@ -417,7 +417,7 @@ class ModelView(BaseModelView):
return
False
else
:
self
.
after_model_delete
(
model
)
return
True
# Default model actions
...
...
flask_admin/contrib/pymongo/view.py
View file @
a51713a0
...
...
@@ -222,7 +222,7 @@ class ModelView(BaseModelView):
query
=
self
.
_search
(
query
,
search
)
# Get count
count
=
self
.
coll
.
find
(
query
)
.
count
()
count
=
self
.
coll
.
find
(
query
)
.
count
()
if
not
self
.
simple_list_pager
else
None
# Sorting
sort_by
=
None
...
...
@@ -337,7 +337,7 @@ class ModelView(BaseModelView):
return
False
else
:
self
.
after_model_delete
(
model
)
return
True
# Default model actions
...
...
flask_admin/contrib/sqla/view.py
View file @
a51713a0
...
...
@@ -4,7 +4,7 @@ import warnings
from
sqlalchemy.orm.attributes
import
InstrumentedAttribute
from
sqlalchemy.orm
import
joinedload
from
sqlalchemy.sql.expression
import
desc
from
sqlalchemy
import
Column
,
Boolean
,
func
,
or_
from
sqlalchemy
import
Boolean
,
func
,
or_
from
sqlalchemy.exc
import
IntegrityError
from
flask
import
flash
...
...
@@ -765,7 +765,7 @@ class ModelView(BaseModelView):
joins
=
set
()
query
=
self
.
get_query
()
count_query
=
self
.
get_count_query
()
count_query
=
self
.
get_count_query
()
if
not
self
.
simple_list_pager
else
None
# Ignore eager-loaded relations (prevent unnecessary joins)
# TODO: Separate join detection for query and count query?
...
...
@@ -781,7 +781,9 @@ class ModelView(BaseModelView):
for
table
in
self
.
_search_joins
:
if
table
.
name
not
in
joins
:
query
=
query
.
outerjoin
(
table
)
count_query
=
count_query
.
outerjoin
(
table
)
if
count_query
is
not
None
:
count_query
=
count_query
.
outerjoin
(
table
)
joins
.
add
(
table
.
name
)
...
...
@@ -795,7 +797,9 @@ class ModelView(BaseModelView):
stmt
=
tools
.
parse_like_term
(
term
)
filter_stmt
=
[
c
.
ilike
(
stmt
)
for
c
in
self
.
_search_fields
]
query
=
query
.
filter
(
or_
(
*
filter_stmt
))
count_query
=
count_query
.
filter
(
or_
(
*
filter_stmt
))
if
count_query
is
not
None
:
count_query
=
count_query
.
filter
(
or_
(
*
filter_stmt
))
# Apply filters
if
filters
and
self
.
_filters
:
...
...
@@ -811,15 +815,20 @@ class ModelView(BaseModelView):
for
table
in
join_tables
:
if
table
.
name
not
in
joins
:
query
=
query
.
join
(
table
)
count_query
=
count_query
.
join
(
table
)
if
count_query
is
not
None
:
count_query
=
count_query
.
join
(
table
)
joins
.
add
(
table
.
name
)
# turn into python format with .clean() and apply filter
query
=
flt
.
apply
(
query
,
flt
.
clean
(
value
))
count_query
=
flt
.
apply
(
count_query
,
flt
.
clean
(
value
))
# Calculate number of rows
count
=
count_query
.
scalar
()
if
count_query
is
not
None
:
count_query
=
flt
.
apply
(
count_query
,
flt
.
clean
(
value
))
# Calculate number of rows if necessary
count
=
count_query
.
scalar
()
if
count_query
else
None
# Auto join
for
j
in
self
.
_auto_joins
:
...
...
@@ -944,7 +953,7 @@ class ModelView(BaseModelView):
return
False
else
:
self
.
after_model_delete
(
model
)
return
True
# Default model actions
...
...
flask_admin/model/base.py
View file @
a51713a0
...
...
@@ -321,6 +321,12 @@ class BaseModelView(BaseView, ActionsMixin):
Controls if the primary key should be displayed in the list view.
"""
simple_list_pager
=
False
"""
Enable or disable simple list pager.
If enabled, model interface would not run count query and will only show prev/next pager buttons.
"""
form
=
None
"""
Form class. Override if you want to use custom form for your model.
...
...
@@ -1486,9 +1492,12 @@ class BaseModelView(BaseView, ActionsMixin):
view_args
.
search
,
view_args
.
filters
)
# Calculate number of pages
num_pages
=
count
//
self
.
page_size
if
count
%
self
.
page_size
!=
0
:
num_pages
+=
1
if
count
is
not
None
:
num_pages
=
count
//
self
.
page_size
if
count
%
self
.
page_size
!=
0
:
num_pages
+=
1
else
:
num_pages
=
None
# Various URL generation helpers
def
pager_url
(
p
):
...
...
@@ -1531,6 +1540,7 @@ class BaseModelView(BaseView, ActionsMixin):
pager_url
=
pager_url
,
num_pages
=
num_pages
,
page
=
view_args
.
page
,
page_size
=
self
.
page_size
,
# Sorting
sort_column
=
view_args
.
sort
,
...
...
flask_admin/templates/bootstrap2/admin/lib.html
View file @
a51713a0
...
...
@@ -76,6 +76,31 @@
{% endif %}
{%- endmacro %}
{% macro simple_pager(page, have_next, generator) -%}
<div
class=
"pagination"
>
<ul>
{% if page > 0 %}
<li>
<a
href=
"{{ generator(page - 1) }}"
>
<
</a>
</li>
{% else %}
<li
class=
"disabled"
>
<a
href=
"{{ generator(0) }}"
>
<
</a>
</li>
{% endif %}
{% if have_next %}
<li>
<a
href=
"{{ generator(page + 1) }}"
>
>
</a>
</li>
{% else %}
<li
class=
"disabled"
>
<a
href=
"{{ generator(page) }}"
>
>
</a>
</li>
{% endif %}
</ul>
</div>
{%- endmacro %}
{# ---------------------- Forms -------------------------- #}
{% macro render_field(form, field, kwargs={}, caller=None) %}
{% set direct_error = h.is_field_error(field.errors) %}
...
...
flask_admin/templates/bootstrap2/admin/model/list.html
View file @
a51713a0
...
...
@@ -13,7 +13,7 @@
{% block model_menu_bar %}
<ul
class=
"nav nav-tabs actions-nav"
>
<li
class=
"active"
>
<a
href=
"javascript:void(0)"
>
{{ _gettext('List') }}
({{ count }})
</a>
<a
href=
"javascript:void(0)"
>
{{ _gettext('List') }}
{% if count %} ({{ count }}){% endif %}
</a>
</li>
{% if admin_view.can_create %}
<li>
...
...
@@ -147,7 +147,13 @@
</tr>
{% endfor %}
</table>
{% block list_pager %}
{% if num_pages is not none %}
{{ lib.pager(page, num_pages, pager_url) }}
{% else %}
{{ lib.simple_pager(page, data|length == page_size, pager_url) }}
{% endif %}
{% endblock %}
{% endblock %}
{{ actionlib.form(actions, get_url('.action_view')) }}
...
...
flask_admin/templates/bootstrap3/admin/lib.html
View file @
a51713a0
...
...
@@ -74,6 +74,29 @@
{% endif %}
{%- endmacro %}
{% macro simple_pager(page, have_next, generator) -%}
<ul
class=
"pagination"
>
{% if page > 0 %}
<li>
<a
href=
"{{ generator(page - 1) }}"
>
<
</a>
</li>
{% else %}
<li
class=
"disabled"
>
<a
href=
"{{ generator(0) }}"
>
<
</a>
</li>
{% endif %}
{% if have_next %}
<li>
<a
href=
"{{ generator(page + 1) }}"
>
>
</a>
</li>
{% else %}
<li
class=
"disabled"
>
<a
href=
"{{ generator(page) }}"
>
>
</a>
</li>
{% endif %}
</ul>
{%- endmacro %}
{# ---------------------- Forms -------------------------- #}
{% macro render_field(form, field, kwargs={}, caller=None) %}
{% set direct_error = h.is_field_error(field.errors) %}
...
...
flask_admin/templates/bootstrap3/admin/model/list.html
View file @
a51713a0
...
...
@@ -13,7 +13,7 @@
{% block model_menu_bar %}
<ul
class=
"nav nav-tabs actions-nav"
>
<li
class=
"active"
>
<a
href=
"javascript:void(0)"
>
{{ _gettext('List') }}
({{ count }})
</a>
<a
href=
"javascript:void(0)"
>
{{ _gettext('List') }}
{% if count %} ({{ count }}){% endif %}
</a>
</li>
{% if admin_view.can_create %}
<li>
...
...
@@ -146,7 +146,13 @@
</tr>
{% endfor %}
</table>
{% block list_pager %}
{% if num_pages is not none %}
{{ lib.pager(page, num_pages, pager_url) }}
{% else %}
{{ lib.simple_pager(page, data|length == page_size, pager_url) }}
{% endif %}
{% endblock %}
{% endblock %}
{{ actionlib.form(actions, get_url('.action_view')) }}
...
...
flask_admin/tests/mongoengine/test_basic.py
View file @
a51713a0
...
...
@@ -948,3 +948,20 @@ def test_form_args_embeddeddoc():
eq_
(
form
.
timestamp
.
label
.
text
,
'Last Updated Time'
)
# This is the failure
eq_
(
form
.
info
.
label
.
text
,
'Information'
)
def
test_simple_list_pager
():
app
,
db
,
admin
=
setup
()
Model1
,
_
=
create_models
(
db
)
class
TestModelView
(
CustomModelView
):
simple_list_pager
=
True
def
get_count_query
(
self
):
assert
False
view
=
TestModelView
(
Model1
)
admin
.
add_view
(
view
)
count
,
data
=
view
.
get_list
(
0
,
None
,
None
,
None
,
None
)
ok_
(
count
is
None
)
flask_admin/tests/sqla/test_basic.py
View file @
a51713a0
...
...
@@ -12,6 +12,7 @@ from . import setup
from
datetime
import
datetime
,
time
,
date
class
CustomModelView
(
ModelView
):
def
__init__
(
self
,
model
,
session
,
name
=
None
,
category
=
None
,
endpoint
=
None
,
url
=
None
,
...
...
@@ -1680,3 +1681,21 @@ def test_safe_redirect():
assert_true
(
rv
.
location
.
startswith
(
'http://localhost/admin/model1/edit/'
))
assert_true
(
'url=
%2
Fadmin
%2
Fmodel1
%2
F'
in
rv
.
location
)
assert_true
(
'id=2'
in
rv
.
location
)
def
test_simple_list_pager
():
app
,
db
,
admin
=
setup
()
Model1
,
_
=
create_models
(
db
)
db
.
create_all
()
class
TestModelView
(
CustomModelView
):
simple_list_pager
=
True
def
get_count_query
(
self
):
assert
False
view
=
TestModelView
(
Model1
,
db
.
session
)
admin
.
add_view
(
view
)
count
,
data
=
view
.
get_list
(
0
,
None
,
None
,
None
,
None
)
assert_true
(
count
is
None
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment