Skip to content

Commit 5420308

Browse files
author
Andrea Cioni
committed
query parameters to query mongodb
1 parent 87487d9 commit 5420308

File tree

9 files changed

+311
-43
lines changed

9 files changed

+311
-43
lines changed

scripts/set_offline_id.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22
import ssl
33
import argparse
44
import pymongo
5+
import bson
56
import uuid
67

78
parser = argparse.ArgumentParser()
89
parser.add_argument('mongo_url',
910
help='URL')
1011
parser.add_argument('db_name',
1112
help='Database name')
13+
parser.add_argument('--user',
14+
default='everyone',
15+
help='Filter by owner')
1216
args = parser.parse_args()
1317

1418
client = pymongo.MongoClient(args.mongo_url, ssl_cert_reqs=ssl.CERT_NONE)
@@ -17,8 +21,13 @@
1721
apply_to = ['shopping_lists', 'recipes', 'menu', 'ingredients']
1822

1923
for coll_name in apply_to:
20-
print('Setting offline_id to:', coll_name)
21-
documents = db[coll_name].find({'offline_id': None})
24+
print('Setting offline_id to:', coll_name, 'owner:', args.user)
25+
26+
if(args.user == 'everyone'):
27+
documents = db[coll_name].find({'offline_id': None})
28+
else:
29+
documents = db[coll_name].find({'offline_id': None, 'owner': bson.ObjectId(args.user)})
30+
2231
for doc in documents:
2332
print('Update doc', doc['_id'])
2433
db[coll_name].update_one({'_id': doc['_id']}, {'$set': {'offline_id': str(uuid.uuid4())}})

tests/test_ingredient.py

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ def delete_ingredient(client, ing_id, auth_headers):
3434
return client.delete('/api/v1/ingredients/{}'.format(ing_id), headers=auth_headers)
3535

3636

37-
def get_all_ingredients(client, auth_headers, page=1, per_page=10):
38-
return client.get('/api/v1/ingredients?page={}&per_page={}'.format(page, per_page), headers=auth_headers)
37+
def get_all_ingredients(client, auth_headers, page=1, per_page=10, order_by='', desc=False):
38+
return client.get('/api/v1/ingredients?page={}&per_page={}&order_by={}&desc={}'.format(page, per_page, order_by, desc), headers=auth_headers)
3939

4040
def get_ingredient(client, ing_id, auth_headers):
4141
return client.get('/api/v1/ingredients/{}'.format(ing_id), headers=auth_headers)
@@ -361,3 +361,100 @@ def test_create_update_timestamp(client: FlaskClient, auth_headers):
361361
and response.json['name'] == 'Tomato' \
362362
and response.json['insert_timestamp'] == insert_timestamp \
363363
and response.json['update_timestamp'] > update_timestamp
364+
365+
366+
def test_get_last_updated(client: FlaskClient, auth_headers):
367+
response = create_ingredient(client, {
368+
'name': 'Rice',
369+
}, auth_headers)
370+
371+
assert response.status_code == 201
372+
373+
idx_1 = response.json['_id']
374+
insert_timestamp_1 = response.json['insert_timestamp']
375+
update_timestamp_1 = response.json['update_timestamp']
376+
377+
response = create_ingredient(client, {
378+
'name': 'Tomato',
379+
}, auth_headers)
380+
381+
assert response.status_code == 201
382+
383+
idx_2 = response.json['_id']
384+
insert_timestamp_2 = response.json['insert_timestamp']
385+
update_timestamp_2 = response.json['update_timestamp']
386+
387+
response = get_all_ingredients(client, auth_headers, order_by='update_timestamp', desc=True, page=1, per_page=1)
388+
389+
assert response.status_code == 200 \
390+
and len(response.json['results']) == 1 \
391+
and response.json['results'][0]['_id'] == idx_2
392+
393+
response = patch_ingredient(client, idx_1, {
394+
'name': 'Rice',
395+
}, auth_headers)
396+
397+
assert response.status_code == 200 \
398+
and response.json['insert_timestamp'] == insert_timestamp_1 \
399+
and response.json['update_timestamp'] > update_timestamp_1
400+
401+
update_timestamp_1 = response.json['update_timestamp']
402+
403+
response = get_all_ingredients(client, auth_headers, order_by='update_timestamp', desc=True, page=1, per_page=1)
404+
405+
assert response.status_code == 200 \
406+
and len(response.json['results']) == 1 \
407+
and response.json['results'][0]['_id'] == idx_1 \
408+
and response.json['results'][0]['update_timestamp'] == update_timestamp_1
409+
410+
response = put_ingredient(client, idx_1, {
411+
'name': 'Rice',
412+
}, auth_headers)
413+
414+
assert response.status_code == 200 \
415+
and response.json['insert_timestamp'] == insert_timestamp_1 \
416+
and response.json['update_timestamp'] > update_timestamp_1
417+
418+
update_timestamp_1 = response.json['update_timestamp']
419+
420+
response = get_all_ingredients(client, auth_headers, order_by='update_timestamp', desc=True, page=1, per_page=1)
421+
422+
assert response.status_code == 200 \
423+
and len(response.json['results']) == 1 \
424+
and response.json['results'][0]['_id'] == idx_1 \
425+
and response.json['results'][0]['update_timestamp'] == update_timestamp_1
426+
427+
response = patch_ingredient(client, idx_2, {
428+
'name': 'Tomato',
429+
}, auth_headers)
430+
431+
assert response.status_code == 200 \
432+
and response.json['insert_timestamp'] == insert_timestamp_2 \
433+
and response.json['update_timestamp'] > update_timestamp_2
434+
435+
update_timestamp_2 = response.json['update_timestamp']
436+
437+
response = get_all_ingredients(client, auth_headers, order_by='update_timestamp', desc=True, page=1, per_page=1)
438+
439+
assert response.status_code == 200 \
440+
and len(response.json['results']) == 1 \
441+
and response.json['results'][0]['_id'] == idx_2 \
442+
and response.json['results'][0]['update_timestamp'] == update_timestamp_2
443+
444+
response = put_ingredient(client, idx_2, {
445+
'name': 'Tomato',
446+
}, auth_headers)
447+
448+
assert response.status_code == 200 \
449+
and response.json['insert_timestamp'] == insert_timestamp_2 \
450+
and response.json['update_timestamp'] > update_timestamp_2
451+
452+
update_timestamp_2 = response.json['update_timestamp']
453+
454+
response = get_all_ingredients(client, auth_headers, order_by='update_timestamp', desc=True, page=1, per_page=1)
455+
456+
assert response.status_code == 200 \
457+
and len(response.json['results']) == 1 \
458+
and response.json['results'][0]['_id'] == idx_2 \
459+
and response.json['results'][0]['update_timestamp'] == update_timestamp_2
460+

tests/test_menu.py

Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ def get_menu(client, menu_id, auth_headers):
3535
return client.get('/api/v1/menus/{}'.format(menu_id), headers=auth_headers)
3636

3737

38-
def get_all_menus(client, auth_headers, page=1, per_page=10):
39-
return client.get('/api/v1/menus?page={}&per_page={}'.format(page, per_page), headers=auth_headers)
38+
def get_all_menus(client, auth_headers, page=1, per_page=10, order_by='', desc=False):
39+
return client.get('/api/v1/menus?page={}&per_page={}&order_by={}&desc={}'.format(page, per_page, order_by, desc), headers=auth_headers)
4040

4141

4242
def get_all_menus_by_day(client, auth_headers, day):
@@ -436,4 +436,100 @@ def test_create_update_timestamp(client: FlaskClient, auth_headers):
436436
assert response.status_code == 200 \
437437
and response.json['date'] == '2020-02-14' \
438438
and response.json['insert_timestamp'] == insert_timestamp \
439-
and response.json['update_timestamp'] > update_timestamp
439+
and response.json['update_timestamp'] > update_timestamp
440+
441+
def test_get_last_updated(client: FlaskClient, auth_headers):
442+
response = create_menu(client, {
443+
'date': '2019-09-06',
444+
}, auth_headers)
445+
446+
assert response.status_code == 201
447+
448+
idx_1 = response.json['_id']
449+
insert_timestamp_1 = response.json['insert_timestamp']
450+
update_timestamp_1 = response.json['update_timestamp']
451+
452+
response = create_menu(client, {
453+
'date': '2019-10-06',
454+
}, auth_headers)
455+
456+
assert response.status_code == 201
457+
458+
idx_2 = response.json['_id']
459+
insert_timestamp_2 = response.json['insert_timestamp']
460+
update_timestamp_2 = response.json['update_timestamp']
461+
462+
response = get_all_menus(client, auth_headers, order_by='update_timestamp', desc=True, page=1, per_page=1)
463+
464+
assert response.status_code == 200 \
465+
and len(response.json['results']) == 1 \
466+
and response.json['results'][0]['_id'] == idx_2
467+
468+
response = patch_menu(client, idx_1, {
469+
'name': 'Rice',
470+
}, auth_headers)
471+
472+
assert response.status_code == 200 \
473+
and response.json['insert_timestamp'] == insert_timestamp_1 \
474+
and response.json['update_timestamp'] > update_timestamp_1
475+
476+
update_timestamp_1 = response.json['update_timestamp']
477+
478+
response = get_all_menus(client, auth_headers, order_by='update_timestamp', desc=True, page=1, per_page=1)
479+
480+
assert response.status_code == 200 \
481+
and len(response.json['results']) == 1 \
482+
and response.json['results'][0]['_id'] == idx_1 \
483+
and response.json['results'][0]['update_timestamp'] == update_timestamp_1
484+
485+
response = put_menu(client, idx_1, {
486+
'date': '2019-10-06',
487+
}, auth_headers)
488+
489+
assert response.status_code == 200 \
490+
and response.json['insert_timestamp'] == insert_timestamp_1 \
491+
and response.json['update_timestamp'] > update_timestamp_1
492+
493+
update_timestamp_1 = response.json['update_timestamp']
494+
495+
response = get_all_menus(client, auth_headers, order_by='update_timestamp', desc=True, page=1, per_page=1)
496+
497+
assert response.status_code == 200 \
498+
and len(response.json['results']) == 1 \
499+
and response.json['results'][0]['_id'] == idx_1 \
500+
and response.json['results'][0]['update_timestamp'] == update_timestamp_1
501+
502+
response = patch_menu(client, idx_2, {
503+
'date': '2019-10-06',
504+
}, auth_headers)
505+
506+
assert response.status_code == 200 \
507+
and response.json['insert_timestamp'] == insert_timestamp_2 \
508+
and response.json['update_timestamp'] > update_timestamp_2
509+
510+
update_timestamp_2 = response.json['update_timestamp']
511+
512+
response = get_all_menus(client, auth_headers, order_by='update_timestamp', desc=True, page=1, per_page=1)
513+
514+
assert response.status_code == 200 \
515+
and len(response.json['results']) == 1 \
516+
and response.json['results'][0]['_id'] == idx_2 \
517+
and response.json['results'][0]['update_timestamp'] == update_timestamp_2
518+
519+
response = put_menu(client, idx_2, {
520+
'date': '2019-10-06',
521+
}, auth_headers)
522+
523+
assert response.status_code == 200 \
524+
and response.json['insert_timestamp'] == insert_timestamp_2 \
525+
and response.json['update_timestamp'] > update_timestamp_2
526+
527+
update_timestamp_2 = response.json['update_timestamp']
528+
529+
response = get_all_menus(client, auth_headers, order_by='update_timestamp', desc=True, page=1, per_page=1)
530+
531+
assert response.status_code == 200 \
532+
and len(response.json['results']) == 1 \
533+
and response.json['results'][0]['_id'] == idx_2 \
534+
and response.json['results'][0]['update_timestamp'] == update_timestamp_2
535+

weekly_menu/webapp/api/__init__.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import re
2+
3+
from datetime import datetime
14
from functools import wraps
25
from flask import request, jsonify, make_response
36
from json import dumps
@@ -10,8 +13,15 @@
1013

1114
from .exceptions import InvalidPayloadSupplied, BadRequest, Forbidden
1215

16+
# Constant fields
17+
1318
API_PREFIX = '/api'
1419

20+
class QueryArgs:
21+
DAY = 'day'
22+
ORDER_BY = 'order_by'
23+
DESC = 'desc'
24+
1525
# Pagination
1626
DEFAULT_PAGE_SIZE = 10
1727

@@ -66,6 +76,44 @@ def wrapper(*args, **kwargs):
6676

6777
return decorate
6878

79+
def parse_query_args(func):
80+
query_args_reqparse = reqparse.RequestParser()
81+
query_args_reqparse.add_argument(
82+
QueryArgs.DAY,
83+
type=str,
84+
location=['args'],
85+
required=False,
86+
default=None
87+
)
88+
query_args_reqparse.add_argument(
89+
QueryArgs.ORDER_BY,
90+
type=str,
91+
location=['args'],
92+
required=False,
93+
default=None
94+
)
95+
query_args_reqparse.add_argument(
96+
QueryArgs.DESC,
97+
type=bool,
98+
location=['args'],
99+
required=False,
100+
default=False
101+
)
102+
@wraps(func)
103+
def wrapper(*args, **kwargs):
104+
query_args = query_args_reqparse.parse_args()
105+
106+
kwargs['query_args'] = {
107+
QueryArgs.DAY: query_args[QueryArgs.DAY],
108+
QueryArgs.ORDER_BY: query_args[QueryArgs.ORDER_BY],
109+
QueryArgs.DESC: query_args[QueryArgs.DESC],
110+
111+
}
112+
113+
return func(*args, **kwargs)
114+
return wrapper
115+
116+
69117

70118
def get_payload(kwname='payload'):
71119
def decorate(func):
@@ -124,7 +172,7 @@ def wrapper(*args, **kwargs):
124172
if per_page <= 0:
125173
raise BadRequest('per_page argument must be greater than zero')
126174

127-
kwargs['req_args'] = {
175+
kwargs['page_args'] = {
128176
'page': page,
129177
'per_page': per_page
130178
}
@@ -175,3 +223,39 @@ def put_embedded_document(new_doc: mongo.EmbeddedDocument, old_doc: mongo.Embedd
175223

176224
def patch_embedded_document(new_doc: mongo.EmbeddedDocument, old_doc: mongo.EmbeddedDocument):
177225
return _update_embedded_document(new_doc, old_doc, patch=True)
226+
227+
228+
def _build_query_by_params(base_query, query_args):
229+
if QueryArgs.DAY in query_args and query_args[QueryArgs.DAY] is not None:
230+
if bool(re.search('^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$', query_args[QueryArgs.DAY])):
231+
try:
232+
searched_day = datetime.strptime(query_args[QueryArgs.DAY], '%Y-%m-%d')
233+
except ValueError as ex:
234+
raise BadRequest('invalid day parameter supplied: {}'.format(ex))
235+
else:
236+
raise BadRequest('invalid day format')
237+
238+
base_query = base_query & Q(date=searched_day)
239+
240+
return base_query
241+
242+
def _apply_ordering(filtered_objects, query_args):
243+
if(query_args[QueryArgs.ORDER_BY] != None and query_args[QueryArgs.ORDER_BY] != ''):
244+
if(query_args[QueryArgs.DESC] == True):
245+
filtered_objects = filtered_objects.order_by('-' + query_args[QueryArgs.ORDER_BY]) # descending "-"
246+
else:
247+
filtered_objects = filtered_objects.order_by('+' + query_args[QueryArgs.ORDER_BY]) # ascending "+"
248+
249+
return filtered_objects
250+
251+
def _apply_pagination(ordered_objects, page_args):
252+
return ordered_objects.paginate(page=page_args['page'], per_page=page_args['per_page'])
253+
254+
def search_on_model(coll_class: mongo.Document.__class__, base_query, query_args, page_args):
255+
query_filter = _build_query_by_params(base_query, query_args)
256+
257+
filtered_objects = coll_class.objects(query_filter)
258+
ordered_objects = _apply_ordering(filtered_objects, query_args)
259+
paginated_objects = _apply_pagination(ordered_objects, page_args)
260+
261+
return paginated_objects

weekly_menu/webapp/api/models/menu.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ class Menu(BaseDocument):
1919
}
2020

2121
def __repr__(self):
22-
return "<Menu '{}'>".format(self.name)
22+
return "<Menu '{}'>".format(self.name)

0 commit comments

Comments
 (0)