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
4e3e7e68
Unverified
Commit
4e3e7e68
authored
Jun 27, 2019
by
Serge S. Koval
Committed by
GitHub
Jun 27, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1875 from flask-admin/hybrid-prop-search
Support search on SQLAlchemy hybrid property
parents
920af0ad
62692891
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
36 additions
and
6 deletions
+36
-6
app.py
examples/sqla/app.py
+8
-1
view.py
flask_admin/contrib/sqla/view.py
+10
-4
test_basic.py
flask_admin/tests/sqla/test_basic.py
+18
-1
No files found.
examples/sqla/app.py
View file @
4e3e7e68
...
...
@@ -4,6 +4,7 @@ from flask import Flask, Markup
from
flask_sqlalchemy
import
SQLAlchemy
from
sqlalchemy.ext.hybrid
import
hybrid_property
from
sqlalchemy.orm
import
composite
from
sqlalchemy
import
sql
,
cast
import
uuid
import
random
import
string
...
...
@@ -85,9 +86,13 @@ class User(db.Model):
def
phone_number
(
self
):
if
self
.
dialling_code
and
self
.
local_phone_number
:
number
=
str
(
self
.
local_phone_number
)
return
"+{} ({}){} {} {}"
.
format
(
self
.
dialling_code
,
number
[
0
],
number
[
1
:
3
],
number
[
3
:
6
],
number
[
6
::])
return
"+{} ({})
{} {} {}"
.
format
(
self
.
dialling_code
,
number
[
0
],
number
[
1
:
3
],
number
[
3
:
6
],
number
[
6
::])
return
@
phone_number
.
expression
def
phone_number
(
cls
):
return
sql
.
operators
.
ColumnOperators
.
concat
(
cast
(
cls
.
dialling_code
,
db
.
String
),
cls
.
local_phone_number
)
def
__str__
(
self
):
return
"{}, {}"
.
format
(
self
.
last_name
,
self
.
first_name
)
...
...
@@ -197,6 +202,7 @@ class UserAdmin(sqla.ModelView):
column_searchable_list
=
[
'first_name'
,
'last_name'
,
'phone_number'
,
'email'
,
]
column_editable_list
=
[
'type'
,
'currency'
,
'timezone'
]
...
...
@@ -233,6 +239,7 @@ class UserAdmin(sqla.ModelView):
FilterEqual
(
column
=
User
.
last_name
,
name
=
'Last Name'
),
FilterLastNameBrown
(
column
=
User
.
last_name
,
name
=
'Last Name'
,
options
=
((
'1'
,
'Yes'
),
(
'0'
,
'No'
))),
'phone_number'
,
'email'
,
'ip_address'
,
'currency'
,
...
...
flask_admin/contrib/sqla/view.py
View file @
4e3e7e68
...
...
@@ -572,14 +572,20 @@ class ModelView(BaseModelView):
if
self
.
column_searchable_list
:
self
.
_search_fields
=
[]
for
p
in
self
.
column_searchable_list
:
attr
,
joins
=
tools
.
get_field_with_path
(
self
.
model
,
p
)
for
name
in
self
.
column_searchable_list
:
attr
,
joins
=
tools
.
get_field_with_path
(
self
.
model
,
name
)
if
not
attr
:
raise
Exception
(
'Failed to find field for search field:
%
s'
%
p
)
raise
Exception
(
'Failed to find field for search field:
%
s'
%
name
)
for
column
in
tools
.
get_columns_for_field
(
attr
):
if
tools
.
is_hybrid_property
(
self
.
model
,
name
):
column
=
attr
if
isinstance
(
name
,
string_types
):
column
.
key
=
name
.
split
(
'.'
)[
-
1
]
self
.
_search_fields
.
append
((
column
,
joins
))
else
:
for
column
in
tools
.
get_columns_for_field
(
attr
):
self
.
_search_fields
.
append
((
column
,
joins
))
return
bool
(
self
.
column_searchable_list
)
...
...
flask_admin/tests/sqla/test_basic.py
View file @
4e3e7e68
...
...
@@ -10,6 +10,7 @@ from flask_admin.contrib.sqla import ModelView, filters, tools
from
flask_babelex
import
Babel
from
sqlalchemy.ext.hybrid
import
hybrid_property
from
sqlalchemy
import
cast
from
sqlalchemy_utils
import
EmailType
,
ChoiceType
,
UUIDType
,
URLType
,
CurrencyType
,
ColorType
,
ArrowType
,
IPAddressType
from
.
import
setup
...
...
@@ -1559,6 +1560,14 @@ def test_hybrid_property():
def
number_of_pixels
(
self
):
return
self
.
width
*
self
.
height
@
hybrid_property
def
number_of_pixels_str
(
self
):
return
str
(
self
.
number_of_pixels
())
@
number_of_pixels_str
.
expression
def
number_of_pixels_str
(
cls
):
return
cast
(
cls
.
width
*
cls
.
height
,
db
.
String
)
db
.
create_all
()
db
.
session
.
add
(
Model1
(
id
=
1
,
name
=
"test_row_1"
,
width
=
25
,
height
=
25
))
...
...
@@ -1571,7 +1580,8 @@ def test_hybrid_property():
Model1
,
db
.
session
,
column_default_sort
=
'number_of_pixels'
,
column_filters
=
[
filters
.
IntGreaterFilter
(
Model1
.
number_of_pixels
,
'Number of Pixels'
)]
'Number of Pixels'
)],
column_searchable_list
=
[
'number_of_pixels_str'
,
]
)
admin
.
add_view
(
view
)
...
...
@@ -1592,6 +1602,13 @@ def test_hybrid_property():
eq_
(
data
[
0
]
.
name
,
'test_row_2'
)
eq_
(
data
[
1
]
.
name
,
'test_row_1'
)
# searching
rv
=
client
.
get
(
'/admin/model1/?search=100'
)
eq_
(
rv
.
status_code
,
200
)
data
=
rv
.
data
.
decode
(
'utf-8'
)
ok_
(
'test_row_2'
in
data
)
ok_
(
'test_row_1'
not
in
data
)
def
test_url_args
():
app
,
db
,
admin
=
setup
()
...
...
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