-
Notifications
You must be signed in to change notification settings - Fork 86
support for flask app factory pattern #85
base: master
Are you sure you want to change the base?
Changes from 14 commits
d35b380
01c976a
6b75fe0
6b1b05c
59f9524
aaf3b56
d85e908
df2155e
2659a1c
25d2fcd
8d91930
52388d7
fb63905
9286060
f833cdb
0edd302
9c06591
a8804b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,16 +2,64 @@ | |
| from flask_mongorest.methods import Create, BulkUpdate, List | ||
|
|
||
|
|
||
| class _DelayedApp(object): | ||
|
|
||
| ''' | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should always use double quotes (as in |
||
| Stores URL rules for later merging with application URL map. | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unnecessary newline |
||
| ''' | ||
|
|
||
| def __init__(self): | ||
| self.url_rules = [] | ||
|
|
||
| def add_url_rule(self, *args, **kwargs): | ||
| self.url_rules.append((args, kwargs)) | ||
|
|
||
|
|
||
| class MongoRest(object): | ||
| def __init__(self, app, **kwargs): | ||
| self.app = app | ||
|
|
||
| def __init__(self, app=None, **kwargs): | ||
| ''' | ||
| Takes optional Flask application instance. If supplied, `init_app` will be | ||
| called to update application url map. | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unnecessary newline |
||
| ''' | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unnecessary newline |
||
| self.url_prefix = kwargs.pop('url_prefix', '') | ||
| app.register_blueprint(Blueprint(self.url_prefix, __name__, template_folder='templates')) | ||
| self.template_folder = kwargs.pop('template_folder', 'templates') | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason why we pop a |
||
| if app is not None: | ||
| self.init_app(app, **kwargs) | ||
| else: | ||
| self.app = _DelayedApp() | ||
|
|
||
| def init_app(self, app): | ||
| ''' | ||
| Provides delayed application instance initialization to support | ||
| Flask application factory pattern. For further details on application | ||
| factories see: | ||
|
|
||
| http://flask.pocoo.org/docs/dev/patterns/appfactories/ | ||
|
|
||
| and | ||
|
|
||
| http://mattupstate.com/python/2013/06/26/how-i-structure-my-flask-applications.html | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unnecessary newline |
||
| ''' | ||
| app.register_blueprint( | ||
| Blueprint(self.url_prefix, | ||
| __name__, | ||
| template_folder=self.template_folder)) | ||
| if hasattr(self, 'app'): | ||
| if isinstance(self.app, _DelayedApp): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. these two
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you have a suggestion for the comment(s)? |
||
| for args, kwargs in self.app.url_rules: | ||
| app.add_url_rule(*args, **kwargs) | ||
| self.app = app | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be better to always set
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that would be cleaner. I will see what works best. |
||
|
|
||
| def register(self, **kwargs): | ||
| def decorator(klass): | ||
|
|
||
| # Construct a url based on a 'name' kwarg with a fallback to a Mongo document's name | ||
| # Construct a url based on a 'name' kwarg with a fallback to a | ||
| # Mongo document's name | ||
| document_name = klass.resource.document.__name__.lower() | ||
| name = kwargs.pop('name', document_name) | ||
| url = kwargs.pop('url', '/%s/' % document_name) | ||
|
|
@@ -24,11 +72,28 @@ def decorator(klass): | |
| 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) | ||
| self.app.add_url_rule( | ||
| url, | ||
| defaults={ | ||
| 'pk': None}, | ||
| view_func=view_func, | ||
| methods=[ | ||
| List.method], | ||
| **kwargs) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This formatting looks a bit extreme. Would this work? |
||
| 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) | ||
| self.app.add_url_rule( | ||
| url, | ||
| view_func=view_func, | ||
| methods=[ | ||
| x.method for x in klass.methods if x in ( | ||
| Create, | ||
| BulkUpdate)], | ||
| **kwargs) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think something like this is much more readable: |
||
| 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) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto - better formatting could be used
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How's this? methods = [x.method for x in klass.methods if x not in (List, BulkUpdate)]
self.app.add_url_rule('%s<%s:%s>/' % (url, pk_type, 'pk'),
view_func=view_func, methods=methods, **kwargs) |
||
| return klass | ||
|
|
||
| return decorator | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -56,6 +56,8 @@ def _dispatch_request(self, *args, **kwargs): | |
| return super(ResourceView, self).dispatch_request(*args, **kwargs) | ||
| except mongoengine.queryset.DoesNotExist as e: | ||
| return {'error': 'Empty query: ' + str(e)}, '404 Not Found' | ||
| except mongoengine.ValidationError as e: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this within the scope of this PR?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know about this one. I'll see how it got in here. |
||
| return {'field-errors': e.errors}, '400 Bad Request' | ||
| except ValidationError as e: | ||
| return e.message, '400 Bad Request' | ||
| except Unauthorized as e: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary newline