Something a bit more on the "magic" side, that some might find relevant https://gist.github.com/Socialery/40141aa2c2d70bd065e8
Things which aren't magic – Flask and app.route
11–20 of 35 posts
Re: Things which aren't magic – Flask and app.route
#12if someone is interested in learning more about building larger scale/production apps with flask, I have a series of tutorials at medium to get you started: https://medium.com/@level09
Disclaimer: I'm the creator of enferno (http://enferno.io), A flask-based system pre-configured with caching/user auth/basic template/ORM/CRUD/task queue/mail functionality.
Re: Things which aren't magic – Flask and app.route
#13As a Python newbie that just recently started using things like Flask and Bottle: wow, that was easy.
Re: Things which aren't magic – Flask and app.route
#14Re: Things which aren't magic – Flask and app.route
#15* Imports shouldn't have side-effects (like registering functions with flask).
* You shouldn't use globals (like the flask app).
* Objects (such as the flask app) should be immutable whenever possible.
None of these are hard-and-fast rules, and Python code has a tendency to give up purity in favor of syntax, so it's certainly justified for Flask to be designed this way, but it's still a bit unsettling, and can lead to bugs, especially in larger cases when your handlers are split up across many files. Some examples:
* You need to make sure that you import every file with a request handler, and those imports often end up unused (only imported for their side-effects), which confuses linters and other static analysis tools.
* It's also easy to accidentally import a new file through some other import chain, so someone rearranging imports later might accidentally disable part of your app by never importing it.
* It can break some "advanced" uses of modules/imports, such as the reload function.
* Test code and scripts that want access to your request handlers are forced to build a (partial) Flask app, even if they have no use for one.
At my job, I recently changed our Flask handlers to be registered with a different approach (but the same API) that avoids most of these issues. Rather than setting things up with side-effects, it makes the route details easy to introspect later. Here's what our implementation of @route() looks like now:
def route(rule, **options):
def route_decorator(func):
# Attach the route rule to the request handler.
func.func_dict.setdefault('_flask_routes', []).append((rule, options))
# Add the request handler to this module's list of handlers.
module = sys.modules[func.__module__]
if not hasattr(module, '_FLASK_HANDLERS'):
module. _FLASK_HANDLERS = {}
module._FLASK_HANDLERS[func.__name__] = func
return func
return route_decorator
So if you have a module called user_routes.py, with 3 Flask request handlers, then user_routes._FLASK_HANDLERS is a list containing those three functions. If one of those handlers is user_routes.create_user, then you can access user_routes.create_user._flask_routes in order to see the names of all of the route strings (usually just one) registered for that request handler.Then, in separate code, there's a list of all modules with request handlers, and we import and introspect all of them as part of a function that sets up and returns the Flask app. So outside code never has any way of accessing a partially-registered Flask app, imports of request handler modules are "pure", and request handlers can often be defined without depending on Flask at all.
Re: Things which aren't magic – Flask and app.route
#16Flask is incredible. since I've made the transition from PHP-based CMS's I've never looked back. if someone is interested in learning more about building larger scale/production apps with flask, I have a series of tutorials at medium to get you started: https://medium.com/@level09 Disclaimer: I'm the creator of enferno ( http://enferno.io ), A flask-based system pre-configured with caching/user auth/basic template/OR…
Re: Things which aren't magic – Flask and app.route
#17Am I right in understanding that decorators are a form of closures as the decorator function is returning the function declared inside it ?
@d
def foo():
...
is equivalent to this code: def foo():
...
foo = d(foo)
(You should think of a Python "def" statement as an action that creates a function and assigns it to a variable, like "foo" in this case. Since functions are first-class values, they can be sent into other functions and assigned again, which is why this works.)But yeah, if you're implementing a decorator (a function from function to function, like "d" above), you can declare an inner function and immediately return it, and that inner function will act as a closure (it will have access to variables in the outer scope). You can take that approach in other situations as well, not just with decorators.
Re: Things which aren't magic – Flask and app.route
#18Am I right in understanding that decorators are a form of closures as the decorator function is returning the function declared inside it ?
Re: Things which aren't magic – Flask and app.route
#19Am I right in understanding that decorators are a form of closures as the decorator function is returning the function declared inside it ?
Re: Things which aren't magic – Flask and app.route
#20Am I right in understanding that decorators are a form of closures as the decorator function is returning the function declared inside it ?
class MyDecorator(object):
def __init__(self, func):
self.func = func
def __call__(self, one, two, three):
# do stuff
return self.func(three, two, one)
ie. you can just as easily use a class instance to store your state, instead of a closure. I routinely use both methods, depending on which is more useful at the time.