Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
ParsePy
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
ParsePy
Commits
6ebd8e7b
Commit
6ebd8e7b
authored
Jul 27, 2013
by
Raphael Lullis
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Django-style query filtering added. Documentation updated.
parent
befdd54f
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
60 additions
and
85 deletions
+60
-85
README.mkd
+4
-21
parse_rest/query.py
+24
-32
parse_rest/tests.py
+32
-32
No files found.
README.mkd
View file @
6ebd8e7b
...
...
@@ -250,31 +250,14 @@ operate on the data, or when you iterate on the Queryset.
#### Filtering
Querysets can be filtered
:
Like Django, Querysets can have constraints added by appending the name of the filter operator to name of the attribute
:
~~~
~~ {python}
high_scores = GameScore.Query.
all().gte(scor
e=1000)
high_scores = GameScore.Query.
filter(score__gt
e=1000)
~~~
~~
The available filter functions are:
*
**Less Than**
*
lt(
**_parameters_
)
*
**Less Than Or Equal To**
*
lte(
**_parameters_
)
*
**Greater Than**
*
gt(
**_parameters_
)
*
**Greater Than Or Equal To**
*
gte(
**_parameters_
)
*
**Not Equal To**
*
ne(
**_parameters_
)
*
**Equal to**
*
eq(
**_parameters_
) // alias: where
**Warning**
: We may change the way to use filtering functions in the
near future, and favor a parameter-suffix based approach (similar to
Django)
You can see the
[
full list of constraint operators defined by
Parse](https://www.parse.com/docs/rest#queries-constraints)
#### Sorting/Ordering
...
...
parse_rest/query.py
View file @
6ebd8e7b
...
...
@@ -15,6 +15,7 @@ import json
import
collections
import
copy
class
QueryResourceDoesNotExist
(
Exception
):
'''Query returned no results'''
pass
...
...
@@ -26,6 +27,7 @@ class QueryResourceMultipleResultsReturned(Exception):
class
QueryManager
(
object
):
def
__init__
(
self
,
model_class
):
self
.
model_class
=
model_class
...
...
@@ -37,29 +39,14 @@ class QueryManager(object):
def
all
(
self
):
return
Queryset
(
self
)
def
where
(
self
,
**
kw
):
return
self
.
all
()
.
where
(
**
kw
)
def
lt
(
self
,
**
kw
):
return
self
.
all
()
.
lt
(
**
kw
)
def
lte
(
self
,
**
kw
):
return
self
.
all
()
.
lte
(
**
kw
)
def
ne
(
self
,
**
kw
):
return
self
.
all
()
.
ne
(
**
kw
)
def
gt
(
self
,
**
kw
):
return
self
.
all
()
.
gt
(
**
kw
)
def
gte
(
self
,
**
kw
):
return
self
.
all
()
.
gte
(
**
kw
)
def
filter
(
self
,
**
kw
):
return
self
.
all
()
.
filter
(
**
kw
)
def
fetch
(
self
):
return
self
.
all
()
.
fetch
()
def
get
(
self
,
**
kw
):
return
self
.
where
(
**
kw
)
.
get
()
return
self
.
filter
(
**
kw
)
.
get
()
class
QuerysetMetaclass
(
type
):
...
...
@@ -67,15 +54,6 @@ class QuerysetMetaclass(type):
def
__new__
(
cls
,
name
,
bases
,
dct
):
cls
=
super
(
QuerysetMetaclass
,
cls
)
.
__new__
(
cls
,
name
,
bases
,
dct
)
# add comparison functions and option functions
for
fname
in
[
'lt'
,
'lte'
,
'gt'
,
'gte'
,
'ne'
]:
def
func
(
self
,
fname
=
fname
,
**
kwargs
):
s
=
copy
.
deepcopy
(
self
)
for
k
,
v
in
kwargs
.
items
():
s
.
_where
[
k
][
'$'
+
fname
]
=
cls
.
convert_to_parse
(
v
)
return
s
setattr
(
cls
,
fname
,
func
)
for
fname
in
[
'limit'
,
'skip'
]:
def
func
(
self
,
value
,
fname
=
fname
):
s
=
copy
.
deepcopy
(
self
)
...
...
@@ -89,11 +67,23 @@ class QuerysetMetaclass(type):
class
Queryset
(
object
):
__metaclass__
=
QuerysetMetaclass
OPERATORS
=
[
'lt'
,
'lte'
,
'gt'
,
'gte'
,
'ne'
,
'in'
,
'nin'
,
'exists'
,
'select'
,
'dontSelect'
,
'all'
]
@staticmethod
def
convert_to_parse
(
value
):
from
datatypes
import
ParseType
return
ParseType
.
convert_to_parse
(
value
)
@classmethod
def
extract_filter_operator
(
cls
,
parameter
):
for
op
in
cls
.
OPERATORS
:
underscored
=
'__
%
s'
%
op
if
parameter
.
endswith
(
underscored
):
return
parameter
[:
-
len
(
underscored
)],
op
return
parameter
,
None
def
__init__
(
self
,
manager
):
self
.
_manager
=
manager
self
.
_where
=
collections
.
defaultdict
(
dict
)
...
...
@@ -111,12 +101,14 @@ class Queryset(object):
return
self
.
_manager
.
_fetch
(
**
options
)
def
where
(
self
,
**
kw
):
return
self
.
eq
(
**
kw
)
def
eq
(
self
,
**
kw
):
def
filter
(
self
,
**
kw
):
for
name
,
value
in
kw
.
items
():
self
.
_where
[
name
]
=
Queryset
.
convert_to_parse
(
value
)
parse_value
=
Queryset
.
convert_to_parse
(
value
)
attr
,
operator
=
Queryset
.
extract_filter_operator
(
name
)
if
operator
is
None
:
self
.
_where
[
attr
]
=
parse_value
else
:
self
.
_where
[
attr
][
'$'
+
operator
]
=
parse_value
return
self
def
order_by
(
self
,
order
,
descending
=
False
):
...
...
parse_rest/tests.py
View file @
6ebd8e7b
...
...
@@ -76,11 +76,11 @@ class TestObject(unittest.TestCase):
city_name
=
getattr
(
self
.
sao_paulo
,
'name'
,
None
)
game_score
=
getattr
(
self
.
score
,
'score'
,
None
)
if
city_name
:
for
city
in
City
.
Query
.
where
(
name
=
city_name
):
for
city
in
City
.
Query
.
filter
(
name
=
city_name
):
city
.
delete
()
if
game_score
:
for
score
in
GameScore
.
Query
.
where
(
score
=
game_score
):
for
score
in
GameScore
.
Query
.
filter
(
score
=
game_score
):
score
.
delete
()
def
testCanInitialize
(
self
):
...
...
@@ -102,7 +102,7 @@ class TestObject(unittest.TestCase):
self
.
assert_
(
object_id
is
not
None
,
'Can not create object'
)
self
.
assert_
(
type
(
object_id
)
==
unicode
)
self
.
assert_
(
type
(
self
.
score
.
createdAt
)
==
datetime
.
datetime
)
self
.
assert_
(
GameScore
.
Query
.
where
(
objectId
=
object_id
)
.
exists
(),
self
.
assert_
(
GameScore
.
Query
.
filter
(
objectId
=
object_id
)
.
exists
(),
'Can not create object'
)
def
testCanUpdateExistingObject
(
self
):
...
...
@@ -118,14 +118,14 @@ class TestObject(unittest.TestCase):
self
.
score
.
save
()
object_id
=
self
.
score
.
objectId
self
.
score
.
delete
()
self
.
assert_
(
not
GameScore
.
Query
.
where
(
objectId
=
object_id
)
.
exists
(),
self
.
assert_
(
not
GameScore
.
Query
.
filter
(
objectId
=
object_id
)
.
exists
(),
'Failed to delete object
%
s on Parse '
%
self
.
score
)
def
testCanIncrementField
(
self
):
previous_score
=
self
.
score
.
score
self
.
score
.
save
()
self
.
score
.
increment
(
'score'
)
self
.
assert_
(
GameScore
.
Query
.
where
(
score
=
previous_score
+
1
)
.
exists
(),
self
.
assert_
(
GameScore
.
Query
.
filter
(
score
=
previous_score
+
1
)
.
exists
(),
'Failed to increment score on backend'
)
def
testAssociatedObject
(
self
):
...
...
@@ -194,61 +194,62 @@ class TestQuery(unittest.TestCase):
def
testExists
(
self
):
"""test the Queryset.exists() method"""
for
s
in
range
(
1
,
6
):
self
.
assert_
(
GameScore
.
Query
.
where
(
score
=
s
)
.
exists
(),
self
.
assert_
(
GameScore
.
Query
.
filter
(
score
=
s
)
.
exists
(),
"exists giving false negative"
)
self
.
assert_
(
not
GameScore
.
Query
.
where
(
score
=
10
)
.
exists
(),
self
.
assert_
(
not
GameScore
.
Query
.
filter
(
score
=
10
)
.
exists
(),
"exists giving false positive"
)
def
test
WhereGet
(
self
):
"""test the Queryset.where() and Queryset.get() methods"""
def
test
CanFilter
(
self
):
'''test the Queryset.filter() method'''
for
s
in
self
.
scores
:
qobj
=
GameScore
.
Query
.
where
(
objectId
=
s
.
objectId
)
.
get
()
qobj
=
GameScore
.
Query
.
filter
(
objectId
=
s
.
objectId
)
.
get
()
self
.
assert_
(
qobj
.
objectId
==
s
.
objectId
,
"Getting object with .
where
() failed"
)
"Getting object with .
filter
() failed"
)
self
.
assert_
(
qobj
.
score
==
s
.
score
,
"Getting object with .
where
() failed"
)
"Getting object with .
filter
() failed"
)
# test the two exceptions get can raise
def
testGetExceptions
(
self
):
'''test possible exceptions raised by Queryset.get() method'''
self
.
assertRaises
(
query
.
QueryResourceDoesNotExist
,
GameScore
.
Query
.
gt
(
score
=
20
)
.
get
)
GameScore
.
Query
.
filter
(
score__gt
=
20
)
.
get
)
self
.
assertRaises
(
query
.
QueryResourceMultipleResultsReturned
,
GameScore
.
Query
.
gt
(
score
=
3
)
.
get
)
GameScore
.
Query
.
filter
(
score__gt
=
3
)
.
get
)
def
testCanQueryDates
(
self
):
last_week
=
datetime
.
datetime
.
now
()
-
datetime
.
timedelta
(
days
=
7
)
score
=
GameScore
(
name
=
'test'
,
last_played
=
last_week
)
score
.
save
()
self
.
assert_
(
GameScore
.
Query
.
where
(
last_played
=
last_week
)
.
exists
(),
self
.
assert_
(
GameScore
.
Query
.
filter
(
last_played
=
last_week
)
.
exists
(),
'Could not run query with dates'
)
def
testComparisons
(
self
):
"""test comparison operators- gt, gte, lt, lte, ne"""
scores_gt_3
=
list
(
GameScore
.
Query
.
all
()
.
gt
(
score
=
3
))
scores_gt_3
=
list
(
GameScore
.
Query
.
filter
(
score__gt
=
3
))
self
.
assertEqual
(
len
(
scores_gt_3
),
2
)
self
.
assert_
(
all
([
s
.
score
>
3
for
s
in
scores_gt_3
]))
scores_gte_3
=
list
(
GameScore
.
Query
.
all
()
.
gte
(
scor
e
=
3
))
scores_gte_3
=
list
(
GameScore
.
Query
.
filter
(
score__gt
e
=
3
))
self
.
assertEqual
(
len
(
scores_gte_3
),
3
)
self
.
assert_
(
all
([
s
.
score
>=
3
for
s
in
scores_gt_3
]))
scores_lt_4
=
list
(
GameScore
.
Query
.
all
()
.
lt
(
score
=
4
))
scores_lt_4
=
list
(
GameScore
.
Query
.
filter
(
score__lt
=
4
))
self
.
assertEqual
(
len
(
scores_lt_4
),
3
)
self
.
assert_
(
all
([
s
.
score
<
4
for
s
in
scores_lt_4
]))
scores_lte_4
=
list
(
GameScore
.
Query
.
all
()
.
lte
(
scor
e
=
4
))
scores_lte_4
=
list
(
GameScore
.
Query
.
filter
(
score__lt
e
=
4
))
self
.
assertEqual
(
len
(
scores_lte_4
),
4
)
self
.
assert_
(
all
([
s
.
score
<=
4
for
s
in
scores_lte_4
]))
scores_ne_2
=
list
(
GameScore
.
Query
.
all
()
.
ne
(
scor
e
=
2
))
scores_ne_2
=
list
(
GameScore
.
Query
.
filter
(
score__n
e
=
2
))
self
.
assertEqual
(
len
(
scores_ne_2
),
4
)
self
.
assert_
(
all
([
s
.
score
!=
2
for
s
in
scores_ne_2
]))
# test chaining
lt_4_gt_2
=
list
(
GameScore
.
Query
.
all
()
.
lt
(
score
=
4
)
.
gt
(
score
=
2
))
self
.
assert_
(
len
(
lt_4_gt_2
)
==
1
,
"chained lt+gt not working"
)
self
.
assert_
(
lt_4_gt_2
[
0
]
.
score
==
3
,
"chained lt+gt not working"
)
q
=
GameScore
.
Query
.
all
()
.
gt
(
score
=
3
)
.
lt
(
score
=
3
)
lt_4_gt_2
=
list
(
GameScore
.
Query
.
filter
(
score__lt
=
4
)
.
filter
(
score__gt
=
2
))
self
.
assert_
(
len
(
lt_4_gt_2
)
==
1
,
'chained lt+gt not working'
)
self
.
assert_
(
lt_4_gt_2
[
0
]
.
score
==
3
,
'chained lt+gt not working'
)
q
=
GameScore
.
Query
.
filter
(
score__gt
=
3
,
score__lt
=
3
)
self
.
assert_
(
not
q
.
exists
(),
"chained lt+gt not working"
)
def
testOptions
(
self
):
...
...
@@ -270,22 +271,21 @@ class TestQuery(unittest.TestCase):
def
testCanCompareDateInequality
(
self
):
today
=
datetime
.
datetime
.
today
()
tomorrow
=
today
+
datetime
.
timedelta
(
days
=
1
)
self
.
assert_
(
GameScore
.
Query
.
lte
(
createdAt
=
tomorrow
)
.
count
()
==
5
,
self
.
assert_
(
GameScore
.
Query
.
filter
(
createdAt__lte
=
tomorrow
)
.
count
()
==
5
,
'Could not make inequality comparison with dates'
)
def
tearDown
(
self
):
"""delete all GameScore objects"""
'''delete all GameScore objects'''
for
s
in
GameScore
.
Query
.
all
():
s
.
delete
()
class
TestFunction
(
unittest
.
TestCase
):
def
setUp
(
self
):
"""create and deploy cloud functions"""
'''create and deploy cloud functions'''
original_dir
=
os
.
getcwd
()
cloud_function_dir
=
os
.
path
.
join
(
os
.
path
.
split
(
__file__
)[
0
],
"cloudcode"
)
cloud_function_dir
=
os
.
path
.
join
(
os
.
path
.
split
(
__file__
)[
0
],
'cloudcode'
)
os
.
chdir
(
cloud_function_dir
)
# write the config file
with
open
(
"config/global.json"
,
"w"
)
as
outf
:
...
...
@@ -339,7 +339,7 @@ class TestUser(unittest.TestCase):
user
and
user
.
delete
()
def
_get_logged_user
(
self
):
if
User
.
Query
.
where
(
username
=
self
.
username
)
.
exists
():
if
User
.
Query
.
filter
(
username
=
self
.
username
)
.
exists
():
return
User
.
login
(
self
.
username
,
self
.
password
)
else
:
return
self
.
_get_user
()
...
...
@@ -377,7 +377,7 @@ class TestUser(unittest.TestCase):
user
.
phone
=
phone_number
user
.
save
()
self
.
assert_
(
User
.
Query
.
where
(
phone
=
phone_number
)
.
exists
(),
self
.
assert_
(
User
.
Query
.
filter
(
phone
=
phone_number
)
.
exists
(),
'Failed to update user data. New info not on Parse'
)
if
__name__
==
"__main__"
:
...
...
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