Skip to content
This repository was archived by the owner on Jan 23, 2024. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
62326a6
separate register_class
tschaume Sep 13, 2019
391e8a2
marshmallow_mongoengine schema, optional cleancat
tschaume Nov 14, 2019
82be891
partial validation and skip primary_key in PUT
tschaume Nov 15, 2019
acea9b4
try_float for numeric operators
tschaume Nov 21, 2019
53ce907
enable nested _fields
tschaume Nov 21, 2019
e0a342b
apply mask in get_queryset
tschaume Nov 21, 2019
3709b33
staticmethod get_optional_fields
tschaume Nov 22, 2019
2fa675f
get full object when updating
tschaume Nov 25, 2019
b6ad8f5
add Decimal128 to MongoEncoder
tschaume Nov 26, 2019
107507c
paginate fields
tschaume Nov 27, 2019
5a30e2b
operators: add swagger type
tschaume Nov 28, 2019
d8bf4df
mongoengine3
tschaume Dec 5, 2019
5a53c5f
get_queryset: fix mask
tschaume Dec 5, 2019
dd6485d
get_queryset: fix mask for nested fields
tschaume Dec 5, 2019
0e68b6d
get_requested_fields: maintain order
tschaume Dec 5, 2019
b26c8a0
minor bugfix
tschaume Dec 6, 2019
c10136d
get_with_list_index; bugfix serialize_list_field
tschaume Dec 6, 2019
8576f44
raise error if total_pages too high
tschaume Dec 8, 2019
39c3d9e
check total_pages before field pagination
tschaume Dec 9, 2019
b521634
add total_count/pages
tschaume Dec 10, 2019
fcb84ce
add page/per_page params as option for _skip/_limit
tschaume Dec 10, 2019
e8c95c0
enable pattern filters
tschaume Dec 11, 2019
be2c11c
enable regex patterns for ordering
tschaume Dec 11, 2019
784b4c5
catch Marshmallow validation errors
tschaume Dec 13, 2019
84fafbe
force_insert and catch NotUniqueError
tschaume Dec 13, 2019
7410b34
wait with save until after checking add permissions
tschaume Dec 19, 2019
893f332
support partial DictField update
tschaume Dec 20, 2019
50253fb
fix DictField update, only return updated fields
tschaume Dec 20, 2019
d7a6f89
enable sort direction
tschaume Dec 24, 2019
17831b1
allow DictField update/set to None
tschaume Jan 6, 2020
78577b4
switch to dotty_dict
tschaume Jan 18, 2020
1d72eb4
return internal dotty dict, check primary key
tschaume Jan 18, 2020
43358ad
also check for id
tschaume Jan 18, 2020
d4242b8
check dot delimiter for primary key
tschaume Jan 19, 2020
c21e150
catch mongoengine ValidationError
tschaume Feb 3, 2020
ac0153f
make_zip mimerender, and Download method
tschaume Feb 13, 2020
c4966ac
short_mime, render_gz
tschaume Feb 14, 2020
30a1c6b
fix mimerender version
tschaume Feb 14, 2020
5dd64f5
add download url after pk
tschaume Feb 14, 2020
e8bbec7
fix url matching
tschaume Feb 14, 2020
b26b54f
catch unset value in csv export
tschaume Feb 15, 2020
537f2c0
render_gz: use cherrypicker for csv
tschaume Feb 27, 2020
49f8b22
BulkCreate and BulkDelete
tschaume Feb 29, 2020
414ef1a
limit bugfix
tschaume Feb 29, 2020
994ad9f
rm bulk_update_limit, respect skip/limit, include has_more/counts
tschaume Mar 3, 2020
5e7df34
add __all__ to methods
tschaume Apr 29, 2020
8c9d860
use glom for path access; skip paginate_fields on Download
tschaume May 21, 2020
7a12eb5
save progress on S3 downloads
tschaume Jun 4, 2020
dc6ca86
fix time import
tschaume Jun 11, 2020
92b5c25
use getattr; allow dynamic fields in queryset mask
tschaume Jun 12, 2020
8ac3f81
apply field pagination to queryset
tschaume Jun 12, 2020
6e72327
include document fields back in queryset mask
tschaume Jun 12, 2020
cd2c194
glom & LazyReference
tschaume Jun 17, 2020
4dcec42
download SSE messages
tschaume Jun 17, 2020
36de94c
channel bugfix
tschaume Jun 18, 2020
f8b9f3e
use ma.utils.get/set_value if available
tschaume Jun 18, 2020
11a90d1
update requirements
tschaume Jun 18, 2020
234c181
catch _Missing
tschaume Jun 18, 2020
e50a9a4
better download logs
tschaume Jun 19, 2020
16f6302
check last_modified for S3 object update
tschaume Jun 20, 2020
0e1a18f
set dict field if unset previously via null
tschaume Jun 30, 2020
3e4794b
use params and set_value
tschaume Jul 15, 2020
f0d9ee9
unflatten raw_data, minor cleanup
tschaume Jul 17, 2020
11cdc11
allow_nan and catch list field
tschaume Jul 18, 2020
2312129
add unflatten dep
tschaume Jul 19, 2020
dc3c7a5
serialize all fields of related resources for download
tschaume Jul 28, 2020
699cdee
identation bugfix
tschaume Jul 28, 2020
84b3043
enable skip post_delete signal
tschaume Jul 28, 2020
af87c36
Bump pymongo from 3.10.1 to 3.11.0
dependabot[bot] Aug 1, 2020
78ddb5a
clean up exception responses
tschaume Sep 17, 2020
2267d88
apply qfilter after params
tschaume Sep 18, 2020
5482c3f
catch undefined exceptions, print traceback
tschaume Sep 21, 2020
666d40f
avoid ServerTimeouts on BulkCreate/Delete
tschaume Sep 30, 2020
233df7d
catch None field_value
tschaume Oct 29, 2020
8e80a45
dependabot PRs
dependabot[bot] Dec 1, 2020
ce27780
use fastnumbers for index access
tschaume Dec 23, 2020
1cfa3ea
remove dangling import; comment reformat
tschaume Dec 23, 2020
4643e57
use bulk_update_limit
tschaume Dec 23, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 42 additions & 21 deletions flask_mongorest/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,46 @@
from flask import Blueprint
from flask_mongorest.methods import Create, BulkUpdate, List
from flask_mongorest.methods import *

def register_class(app, klass, **kwargs):
# Construct a url based on a 'name' kwarg with a fallback to the
# view's class name. Note that the name must be unique.
name = kwargs.pop('name', klass.__name__)
view_func = klass.as_view(name)
url = kwargs.pop('url', None)
if not url:
document_name = klass.resource.document.__name__.lower()
url = f'/{document_name}/'

# Insert the url prefix, if it exists
url_prefix = kwargs.pop('url_prefix', '')
if url_prefix:
url = f'{url_prefix}{url}'

# Add url rules
klass_methods = set(klass.methods)
if Create in klass_methods and BulkCreate in klass_methods:
raise ValueError('Use either Create or BulkCreate!')

for x in klass_methods & {Fetch, Update, Delete}:
endpoint = view_func.__name__ + x.__name__
app.add_url_rule(
f'{url}<string:pk>/', defaults={'short_mime': None},
view_func=view_func, methods=[x.method], endpoint=endpoint, **kwargs
)

for x in klass_methods & {Create, BulkFetch, BulkCreate, BulkUpdate, BulkDelete}:
endpoint = view_func.__name__ + x.__name__
app.add_url_rule(
url, defaults={'pk': None, 'short_mime': None},
view_func=view_func, methods=[x.method], endpoint=endpoint, **kwargs
)

if Download in klass.methods:
endpoint = view_func.__name__ + Download.__name__
app.add_url_rule(
f'{url}download/<string:short_mime>/', defaults={'pk': None, 'short_mime': 'gz'},
view_func=view_func, methods=[Download.method], endpoint=endpoint, **kwargs
)

class MongoRest(object):
def __init__(self, app, **kwargs):
Expand All @@ -10,26 +50,7 @@ def __init__(self, app, **kwargs):

def register(self, **kwargs):
def decorator(klass):
# Construct a url based on a 'name' kwarg with a fallback to the
# view's class name. Note that the name must be unique.
name = kwargs.pop('name', klass.__name__)
url = kwargs.pop('url', None)
if not url:
document_name = klass.resource.document.__name__.lower()
url = '/%s/' % document_name

# Insert the url prefix, if it exists
if self.url_prefix:
url = '%s%s' % (self.url_prefix, url)

# Add url rules
pk_type = kwargs.pop('pk_type', 'string')
view_func = klass.as_view(name)
if List in klass.methods:
self.app.add_url_rule(url, defaults={'pk': None}, view_func=view_func, methods=[List.method], **kwargs)
if Create in klass.methods or BulkUpdate in klass.methods:
self.app.add_url_rule(url, view_func=view_func, methods=[x.method for x in klass.methods if x in (Create, BulkUpdate)], **kwargs)
self.app.add_url_rule('%s<%s:%s>/' % (url, pk_type, 'pk'), view_func=view_func, methods=[x.method for x in klass.methods if x not in (List, BulkUpdate)], **kwargs)
register_class(self.app, klass, **kwargs)
return klass

return decorator
Expand Down
27 changes: 22 additions & 5 deletions flask_mongorest/methods.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
import sys
import inspect

class Fetch:
method = 'GET'

class Create:
method = 'POST'

class Update:
method = 'PUT'

class Delete:
method = 'DELETE'


class BulkFetch:
method = 'GET'

class BulkCreate:
method = 'POST'

class BulkUpdate:
method = 'PUT'

class Fetch:
method = 'GET'
class BulkDelete:
method = 'DELETE'


class List:
class Download:
method = 'GET'

class Delete:
method = 'DELETE'
members = inspect.getmembers(sys.modules[__name__], inspect.isclass)
__all__ = [m[0] for m in members]
25 changes: 25 additions & 0 deletions flask_mongorest/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class Operator(object):
"""Base class that all the other operators should inherit from."""

op = 'exact'
typ = 'string'

# Can be overridden via constructor.
allow_negation = False
Expand All @@ -75,20 +76,42 @@ def apply(self, queryset, field, value, negate=False):
kwargs = self.prepare_queryset_kwargs(field, value, negate)
return queryset.filter(**kwargs)

def try_float(value):
try:
return float(value)
except ValueError:
return value

class Ne(Operator):
op = 'ne'

class Lt(Operator):
op = 'lt'
typ = 'number'

def prepare_queryset_kwargs(self, field, value, negate):
return {'__'.join(filter(None, [field, self.op])): try_float(value)}

class Lte(Operator):
op = 'lte'
typ = 'number'

def prepare_queryset_kwargs(self, field, value, negate):
return {'__'.join(filter(None, [field, self.op])): try_float(value)}

class Gt(Operator):
op = 'gt'
typ = 'number'

def prepare_queryset_kwargs(self, field, value, negate):
return {'__'.join(filter(None, [field, self.op])): try_float(value)}

class Gte(Operator):
op = 'gte'
typ = 'number'

def prepare_queryset_kwargs(self, field, value, negate):
return {'__'.join(filter(None, [field, self.op])): try_float(value)}

class Exact(Operator):
op = 'exact'
Expand All @@ -106,6 +129,7 @@ class IExact(Operator):

class In(Operator):
op = 'in'
typ = 'array'

def prepare_queryset_kwargs(self, field, value, negate):
# this is null if the user submits an empty in expression (like
Expand Down Expand Up @@ -140,6 +164,7 @@ class IEndswith(Operator):

class Boolean(Operator):
op = 'exact'
typ = 'boolean'

def prepare_queryset_kwargs(self, field, value, negate):
if value == 'false':
Expand Down
Loading