', methods=['GET', 'PUT', 'DELETE', 'PATCH'])
56 | @conditional
57 | def view(path):
58 | try:
59 | # SHA1 should generate well-behaved etags
60 | etag = hashlib.sha1(d[path]).hexdigest()
61 | if flask.request.method == 'GET':
62 | response = flask.make_response(d[path])
63 | response.set_etag(etag)
64 | else:
65 | response = flask.Response(status=204)
66 | del response.headers['content-type']
67 | response.set_etag(etag)
68 | if flask.request.method == 'DELETE':
69 | del d[path]
70 | del response.headers['etag']
71 | else:
72 | if flask.request.method == 'PUT':
73 | d[path] = flask.request.data
74 | else: # (PATCH)
75 | # Lame PATCH technique
76 | d[path] += flask.request.data
77 | response.set_etag(hashlib.sha1(d[path]).hexdigest())
78 | return response
79 | except KeyError:
80 | flask.abort(404)
81 |
82 |
83 | class NotModified(werkzeug.exceptions.HTTPException):
84 | code = 304
85 | def get_response(self, environment):
86 | return flask.Response(status=304)
87 |
88 |
89 | class PreconditionRequired(werkzeug.exceptions.HTTPException):
90 | code = 428
91 | description = ('This request is required to be '
92 | 'conditional; try using "If-Match".')
93 | name = 'Precondition Required'
94 | def get_response(self, environment):
95 | resp = super(PreconditionRequired,
96 | self).get_response(environment)
97 | resp.status = str(self.code) + ' ' + self.name.upper()
98 | return resp
99 |
100 |
101 | if __name__ == "__main__":
102 | app.run()
103 | # Testing with curl
104 | # $ curl -i localhost:5000/a
105 |
106 | # $ curl -iH 'If-None-Match: \
107 | # "56eaadbbd9fa287e7270cf13a41083c94f52ab9b"' localhost:5000/a
108 |
109 | # $ curl -iX DELETE localhost:5000/a
110 |
111 | # $ curl -iX DELETE -H 'If-Match: "badmatch"' localhost:5000/a
112 |
113 | # $ curl -iX DELETE -H 'If-Match: \
114 | # "56eaadbbd9fa287e7270cf13a41083c94f52ab9b"' localhost:5000/a
115 |
116 | # $ curl -i localhost:5000/a
117 |
--------------------------------------------------------------------------------
/decorators/http_access_control.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | decorators.access_control
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Decorator for the HTTP Access Control
7 | http://flask.pocoo.org/snippets/56/
8 | """
9 |
10 | from datetime import timedelta
11 | import os
12 | import sys
13 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
14 | from functools import update_wrapper
15 |
16 | from flask import make_response, request, current_app, jsonify
17 |
18 | from app import app
19 |
20 |
21 | def crossdomain(origin=None, methods=None, headers=None, max_age=21600,
22 | attach_to_all=True, automatic_options=True):
23 | if methods is not None:
24 | methods = ', '.join(sorted(x.upper() for x in methods))
25 | if headers is not None and not isinstance(headers, basestring):
26 | headers = ', '.join(x.upper() for x in headers)
27 | if not isinstance(origin, basestring):
28 | origin = ', '.join(origin)
29 | if isinstance(max_age, timedelta):
30 | max_age = max_age.total_seconds()
31 |
32 | def get_methods():
33 | if methods is not None:
34 | return methods
35 |
36 | options_resp = current_app.make_default_options_response()
37 | return options_resp.headers['allow']
38 |
39 | def decorator(f):
40 | def wrapped_function(*args, **kwargs):
41 | if automatic_options and request.method == 'OPTIONS':
42 | resp = current_app.make_default_options_response()
43 | else:
44 | resp = make_response(f(*args, **kwargs))
45 | if not attach_to_all and request.method != 'OPTIONS':
46 | return resp
47 |
48 | h = resp.headers
49 |
50 | h['Access-Control-Allow-Origin'] = origin
51 | h['Access-Control-Allow-Methods'] = get_methods()
52 | h['Access-Control-Max-Age'] = str(max_age)
53 | if headers is not None:
54 | h['Access-Control-Allow-Headers'] = headers
55 | return resp
56 |
57 | f.provide_automatic_options = False
58 | return update_wrapper(wrapped_function, f)
59 | return decorator
60 |
61 |
62 | @app.route('/my_service')
63 | @crossdomain(origin='*')
64 | def my_service():
65 | return jsonify(foo='cross domain ftw')
66 |
67 |
68 | if __name__ == "__main__":
69 | app.run()
70 |
--------------------------------------------------------------------------------
/decorators/http_headers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | decorators.headers
4 | ~~~~~~~~~~~~~~~~~~
5 |
6 | Generic HTTP headers decorator
7 | http://flask.pocoo.org/snippets/100/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | from functools import wraps
14 |
15 | from flask import make_response
16 |
17 | from app import app
18 |
19 |
20 | def add_response_headers(headers={}):
21 | """This decorator adds the headers passed in to the response"""
22 | def decorator(f):
23 | @wraps(f)
24 | def decorated_function(*args, **kwargs):
25 | resp = make_response(f(*args, **kwargs))
26 | h = resp.headers
27 | for header, value in headers.items():
28 | h[header] = value
29 | return resp
30 | return decorated_function
31 | return decorator
32 |
33 |
34 | def noindex(f):
35 | """This decorator passes X-Robots-Tag: noindex"""
36 | return add_response_headers({'X-Robots-Tag': 'noindex'})(f)
37 |
38 |
39 | @app.route('/')
40 | @noindex
41 | def no_indexed():
42 | """
43 | This page will be served with X-Robots-Tag: noindex
44 | in the response headers
45 | """
46 | return "Check my headers!"
47 |
48 |
49 | if __name__ == "__main__":
50 | app.run()
51 | # check the headers with: curl -I http://0.0.0.0:5000/
52 |
--------------------------------------------------------------------------------
/decorators/jsonp.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | decorators.jsonp
4 | ~~~~~~~~~~~~~~~~
5 |
6 | JSONP decorator
7 | http://flask.pocoo.org/snippets/79/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | from functools import wraps
14 |
15 | from flask import request, current_app
16 | from flask import jsonify
17 |
18 | from app import app
19 |
20 |
21 | def jsonp(func):
22 | """Wraps JSONified output for JSONP requests."""
23 | @wraps(func)
24 | def decorated_function(*args, **kwargs):
25 | callback = request.args.get('callback', False)
26 | if callback:
27 | data = str(func(*args, **kwargs).data)
28 | content = str(callback) + '(' + data + ')'
29 | mimetype = 'application/javascript'
30 | return current_app.response_class(content, mimetype=mimetype)
31 | else:
32 | return func(*args, **kwargs)
33 | return decorated_function
34 |
35 |
36 | @app.route('/')
37 | @jsonp
38 | def jsonped():
39 | return jsonify({"foo": "bar"})
40 |
41 |
42 | if __name__ == "__main__":
43 | app.run()
44 |
--------------------------------------------------------------------------------
/decorators/rate_limit_with_redis.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | decorators.redis_ratelimit
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Rate Limiting Decorator with Redis
7 | http://flask.pocoo.org/snippets/70/
8 | """
9 |
10 | import os
11 | import sys
12 | import time
13 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
14 | from functools import update_wrapper
15 |
16 | from flask import request, g
17 | from redis import Redis
18 | import redis
19 |
20 | from app import app
21 |
22 |
23 | # Connecting to Redis
24 | redis = Redis()
25 |
26 |
27 | class RateLimit(object):
28 | expiration_window = 10
29 |
30 | def __init__(self, key_prefix, limit, per, send_x_headers):
31 | self.reset = (int(time.time()) // per) * per + per
32 | self.key = key_prefix + str(self.reset)
33 | self.limit = limit
34 | self.per = per
35 | self.send_x_headers = send_x_headers
36 | p = redis.pipeline()
37 | p.incr(self.key)
38 | p.expireat(self.key, self.reset + self.expiration_window)
39 | self.current = min(p.execute()[0], limit)
40 |
41 | remaining = property(lambda x: x.limit - x.current)
42 | over_limit = property(lambda x: x.current >= x.limit)
43 |
44 |
45 | def get_view_rate_limit():
46 | return getattr(g, '_view_rate_limit', None)
47 |
48 |
49 | def on_over_limit(limit):
50 | return 'You hit the rate limit', 400
51 |
52 |
53 | def ratelimit(limit, per=300, send_x_headers=True, over_limit=on_over_limit,
54 | scope_func=lambda: request.remote_addr,
55 | key_func=lambda: request.endpoint):
56 | def decorator(f):
57 | def rate_limited(*args, **kwargs):
58 | key = 'rate-limit/%s/%s/' % (key_func(), scope_func())
59 | rlimit = RateLimit(key, limit, per, send_x_headers)
60 | g._view_rate_limit = rlimit
61 | if over_limit is not None and rlimit.over_limit:
62 | return over_limit(rlimit)
63 | return f(*args, **kwargs)
64 | return update_wrapper(rate_limited, f)
65 | return decorator
66 |
67 |
68 | @app.after_request
69 | def inject_x_rate_header(response):
70 | limit = get_view_rate_limit()
71 | if limit and limit.send_x_headers:
72 | h = response.headers
73 | h.add('X-RateLimit-Remaining', str(limit.remaining))
74 | h.add('X-RateLimit-Limit', str(limit.limit))
75 | h.add('X-RateLimit-Reset', str(limit.reset))
76 | return response
77 |
78 |
79 | @app.route('/rate-limited')
80 | @ratelimit(limit=300, per=50 * 15)
81 | def index():
82 | return '
This is a rate limited response
'
83 |
84 |
85 | def main():
86 | app.debug = False
87 | app.run()
88 |
89 |
90 | if __name__ == "__main__":
91 | from threading import Thread
92 | server = Thread(target=main)
93 | server.setDaemon(True)
94 | server.start()
95 | client = app.test_client()
96 | times = 0
97 | while True:
98 | times += 1
99 | rv = client.get('/rate-limited')
100 | if rv.status_code == 200:
101 | continue
102 | elif rv.status_code == 400:
103 | print 'The %s times visiting...' % times
104 | print 'Response body: ' + rv.data
105 | break
106 |
--------------------------------------------------------------------------------
/decorators/ssl_view.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | decorators.sslview
4 | ~~~~~~~~~~~~~~~~~~
5 |
6 | SSL for particular views
7 | http://flask.pocoo.org/snippets/93/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | from functools import wraps
14 |
15 | from flask import request, current_app, redirect
16 |
17 | from app import app
18 |
19 |
20 | def ssl_required(fn):
21 | @wraps(fn)
22 | def decorated_view(*args, **kwargs):
23 | if current_app.config.get("SSL"):
24 | if request.is_secure:
25 | return fn(*args, **kwargs)
26 | else:
27 | return redirect(request.url.replace("http://", "https://"))
28 |
29 | return fn(*args, **kwargs)
30 |
31 | return decorated_view
32 |
33 |
34 | @app.route('/')
35 | @ssl_required
36 | def index():
37 | return "ssl_required"
38 |
39 |
40 | if __name__ == "__main__":
41 | app.config["SSL"] = True
42 | app.run()
43 |
--------------------------------------------------------------------------------
/decorators/view_render.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | decorators.view_render
4 | ~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | View Rendering Decorator
7 | http://flask.pocoo.org/snippets/18/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | from functools import wraps
14 |
15 | from werkzeug import BaseResponse
16 |
17 | from app import app
18 |
19 |
20 | def render_html(template, **defaults):
21 | def wrapped(result):
22 | variables = defaults.copy()
23 | variables.update(result)
24 | return render_template(template, **variables)
25 | return wrapped
26 |
27 |
28 | def view(self, url, renderer=None, *args, **kwargs):
29 | super_route = self.route
30 |
31 | defaults = kwargs.pop('defaults', {})
32 | route_id = object()
33 | defaults['_route_id'] = route_id
34 |
35 | def deco(f):
36 | @super_route(url, defaults=defaults, *args, **kwargs)
37 | @wraps(f)
38 | def decorated_function(*args, **kwargs):
39 | this_route = kwargs.get('_route_id')
40 | if not getattr(f, 'is_route', False):
41 | del kwargs['_route_id']
42 |
43 | result = f(*args, **kwargs)
44 |
45 | if this_route is not route_id:
46 | return result
47 |
48 | # catch redirects.
49 | if isinstance(result, (app.response_class,
50 | BaseResponse)):
51 | return result
52 |
53 | if renderer is None:
54 | return result
55 | return renderer(result)
56 |
57 | decorated_function.is_route = True
58 | return decorated_function
59 |
60 | return deco
61 |
62 |
63 | @view(app, '/', render_html('page.html'))
64 | def show_page(name):
65 | page = load_page(name)
66 | return dict(title=page.title, contents=page.contents)
67 |
68 |
69 | if __name__ == "__main__":
70 | app.run()
71 |
--------------------------------------------------------------------------------
/deployment/apache_host.wsgi:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import sys, os
3 | sys.path.insert(0, '/var/www/myapp')
4 | os.chdir("/var/www/myapp")
5 | from srv import app as application
6 |
--------------------------------------------------------------------------------
/deployment/cherokee_fix.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | deployment.cherokee_fix
4 | ~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Cherokee fix for URL prefix
7 | http://flask.pocoo.org/snippets/84/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response
15 |
16 | from app import app
17 |
18 |
19 | class CherrokeeFix(object):
20 |
21 | def __init__(self, app, script_name):
22 | self.app = app
23 | self.script_name = script_name
24 |
25 | def __call__(self, environ, start_response):
26 | path = environ.get('SCRIPT_NAME', '') + environ.get('PATH_INFO', '')
27 | environ['SCRIPT_NAME'] = self.script_name
28 | environ['PATH_INFO'] = path[len(self.script_name):]
29 | assert path[:len(self.script_name)] == self.script_name
30 | return self.app(environ, start_response)
31 |
32 |
33 | @app.route('/')
34 | def index():
35 | return 'index'
36 |
37 |
38 | if __name__ == "__main__":
39 | app.wsgi_app = CherrokeeFix(app.wsgi_app, '/test')
40 | app.run()
41 |
--------------------------------------------------------------------------------
/deployment/dotcloud.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | deployment.dotcloud
4 | ~~~~~~~~~~~~~~~~~~~
5 |
6 | Deploying a Flask app on Dotcloud
7 | http://flask.pocoo.org/snippets/48/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response
15 |
16 | from app import app
17 |
18 |
19 | """
20 | How to deploy a Flask app on Dotcloud
21 | Create the namespace you want:
22 |
23 | dotcloud create
24 | A DotCloud application is described by a build file, which is a simple YAML file named "dotcloud.yml" located in your local source directory. To add a new python service to your app, just add the following lines to /dotcloud.yml:
25 |
26 | www:
27 | type: python
28 | Now create a /wsgi.py file containing:
29 |
30 | import sys
31 | sys.path.append('/home/dotcloud/current')
32 | from import app as application
33 | /home/dotcloud/current is the default path to your app on the server.
34 |
35 | Eventually, create nginx.conf and uwsgi.conf in the source folder. See Dotcloud documentation for further information.
36 |
37 | Create your requirements.txt file:
38 |
39 | pip freeze > ./requirements.txt
40 | Now, make sure that your source folder contains at least:
41 |
42 | ./
43 | ../
44 | ./
45 | ./static
46 | ./__init__.py
47 | ./ ...
48 | ./requirements.txt
49 | ./wsgi.py
50 | ./dotcloud.yml
51 | ./ ...
52 | Create a symbolic link to your static folder:
53 |
54 | cd
55 | ln -s /static static
56 | You can now push the code to Dotcloud:
57 |
58 | dotcloud push
59 | A random URL has been generated for your python service in your application (something like http://my4ppr0x.dotcloud.com/). Point your browser to this URL to see your new app running.
60 | """
61 |
62 |
63 | @app.route('/')
64 | def index():
65 | return 'index'
66 |
67 |
68 | if __name__ == "__main__":
69 | app.run()
70 |
--------------------------------------------------------------------------------
/deployment/fix_connection_reset_post.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | deployment.fix_post_reset
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Fix for Connection Reset on POST
7 | http://flask.pocoo.org/snippets/47/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response
15 | from werkzeug.wsgi import LimitedStream
16 |
17 | from app import app
18 |
19 |
20 | class StreamConsumingMiddleware(object):
21 |
22 | def __init__(self, app):
23 | self.app = app
24 |
25 | def __call__(self, environ, start_response):
26 | stream = LimitedStream(environ['wsgi.input'],
27 | int(environ['CONTENT_LENGTH'] or 0))
28 | environ['wsgi.input'] = stream
29 | app_iter = self.app(environ, start_response)
30 | try:
31 | stream.exhaust()
32 | for event in app_iter:
33 | yield event
34 | finally:
35 | if hasattr(app_iter, 'close'):
36 | app_iter.close()
37 |
38 |
39 | @app.route('/')
40 | def index():
41 | return 'index'
42 |
43 |
44 | if __name__ == "__main__":
45 | app.wsgi_app = StreamConsumingMiddleware(app.wsgi_app)
46 | app.run()
47 |
--------------------------------------------------------------------------------
/deployment/fix_url_behind_reverse.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | deployment.reverse_url_fix
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Fixing SCRIPT_NAME/url_scheme when behind reverse proxy
7 | http://flask.pocoo.org/snippets/35/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response
15 |
16 | from app import app
17 |
18 |
19 | class ReverseProxied(object):
20 | '''Wrap the application in this middleware and configure the
21 | front-end server to add these headers, to let you quietly bind
22 | this to a URL other than / and to an HTTP scheme that is
23 | different than what is used locally.
24 |
25 | In nginx:
26 | location /myprefix {
27 | proxy_pass http://192.168.0.1:5001;
28 | proxy_set_header Host $host;
29 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
30 | proxy_set_header X-Scheme $scheme;
31 | proxy_set_header X-Script-Name /myprefix;
32 | }
33 |
34 | :param app: the WSGI application
35 | '''
36 | def __init__(self, app):
37 | self.app = app
38 |
39 | def __call__(self, environ, start_response):
40 | script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
41 | if script_name:
42 | environ['SCRIPT_NAME'] = script_name
43 | path_info = environ['PATH_INFO']
44 | if path_info.startswith(script_name):
45 | environ['PATH_INFO'] = path_info[len(script_name):]
46 |
47 | scheme = environ.get('HTTP_X_SCHEME', '')
48 | if scheme:
49 | environ['wsgi.url_scheme'] = scheme
50 | return self.app(environ, start_response)
51 |
52 |
53 | @app.route('/')
54 | def index():
55 | return 'index'
56 |
57 |
58 | if __name__ == "__main__":
59 | app.wsgi_app = ReverseProxied(app.wsgi_app)
60 | app.run()
61 |
--------------------------------------------------------------------------------
/deployment/pass_remote_user.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | deployment.pass_remote_user
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Passing REMOTE_USER from Apache as a reverse proxy to web application servers
7 | http://flask.pocoo.org/snippets/69/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response
15 |
16 | from app import app
17 |
18 |
19 | """
20 | RequestHeader set X-Proxy-REMOTE-USER %{REMOTE_USER}
21 | """
22 |
23 |
24 | class RemoteUserMiddleware(object):
25 | def __init__(self, app):
26 | self.app = app
27 | def __call__(self, environ, start_response):
28 | user = environ.pop('HTTP_X_PROXY_REMOTE_USER', None)
29 | environ['REMOTE_USER'] = user
30 | return self.app(environ, start_response)
31 |
32 |
33 | @app.route('/')
34 | def index():
35 | return 'index'
36 |
37 |
38 | if __name__ == "__main__":
39 | app.wsgi_app = RemoteUserMiddleware(app.wsgi_app)
40 | app.run()
41 |
--------------------------------------------------------------------------------
/deployment/webfaction.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | deployment.webfaction
4 | ~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Deploying a Flask app on Webfaction
7 | http://flask.pocoo.org/snippets/65/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response
15 |
16 | from app import app
17 |
18 |
19 | """
20 | Webfaction is a Python friendly hosting with affordable pricing and tons of useful features.
21 |
22 | To deploy a Flask application on Webfaction you should follow these steps:
23 |
24 | Create an application in Webfaction control panel choosing "mod_wsgi 3.2/Python 2.6" or another one of the available Python version.
25 | The system will automagically create some folder under the webapps directory in your home folder
26 | webapps/yourapplication/
27 | |-- apache2
28 | | |-- bin
29 | | |-- conf
30 | | |-- lib
31 | | |-- logs
32 | | `-- modules
33 | `-- htdocs
34 | Install Flask and all the extensions you need using easy_install:
35 | foo@bar:~$ easy_install-2.6 Flask
36 | Note that Webfaction gives you different easy_install executables: use the one that meets the Python version you choose when the application was created.
37 |
38 | Open webapps/yourapp/index.py delete the content and add the following line:
39 | from yourapp import app as application
40 | Modify your webapps/yourapp/apache2/conf/httpd.conf. At the bottom of the file add the following lines changing yourapp and yourusername according to your setup:
41 | WSGIPythonPath /home/yourusername/webapps/yourapp/htdocs/
42 | #If you do not specify the following directive the app *will* work but you will
43 | #see index.py in the path of all URLs
44 | WSGIScriptAlias / /home/yourusername/webapps/yourapp/htdocs/index.py
45 |
46 |
47 | AddHandler wsgi-script .py
48 | RewriteEngine on
49 | RewriteBase /
50 | WSGIScriptReloading On
51 |
52 | If you have choosed / as the mout point for your application you are done. If you mounted the application somewhere else (i.e. /blog) there is some additional work to do.
53 |
54 | You need to write a WSGI middleware that prefixes SCRIPT_NAME with that prefix otherwise the url_for function will not be able to create the correct URLs for you (the following snippets is kindly provided by Armin himself).
55 |
56 | class WebFactionMiddleware(object):
57 | def __init__(self, app):
58 | self.app = app
59 | def __call__(self, environ, start_response):
60 | environ['SCRIPT_NAME'] = '/yourapp'
61 | return self.app(environ, start_response)
62 |
63 | app.wsgi_app = WebFactionMiddleware(app.wsgi_app)
64 | You can put this snippet in the application's __init__.py.
65 |
66 | Happy Flasking!
67 | """
68 |
69 |
70 | @app.route('/')
71 | def index():
72 | return 'index'
73 |
74 |
75 | if __name__ == "__main__":
76 | app.run()
77 |
--------------------------------------------------------------------------------
/forms/complex_validation.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | forms.complex_validation
4 | ~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Complex Validation with Flask-WTF
7 | http://flask.pocoo.org/snippets/64/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import render_template, url_for, redirect
15 | from flask.wtf import Form, TextField, PasswordField, validators
16 |
17 | from app import app
18 | from models import User
19 |
20 |
21 | class LoginForm(Form):
22 | username = TextField('Username', [validators.Required()])
23 | password = PasswordField('Password', [validators.Required()])
24 |
25 | def __init__(self, *args, **kwargs):
26 | Form.__init__(self, *args, **kwargs)
27 | self.user = None
28 |
29 | def validate(self):
30 | rv = Form.validate(self)
31 | if not rv:
32 | return False
33 |
34 | user = User.query.filter_by(
35 | username=self.username.data).first()
36 | if user is None:
37 | self.username.errors.append('Unknown username')
38 | return False
39 |
40 | if not user.check_password(self.password.data):
41 | self.password.errors.append('Invalid password')
42 | return False
43 |
44 | self.user = user
45 | return True
46 |
47 |
48 | @app.route('/login', methods=['GET', 'POST'])
49 | def login():
50 | form = LoginForm()
51 | if form.validate_on_submit():
52 | flash(u'Successfully logged in as %s' % form.user.username)
53 | session['user_id'] = form.user.id
54 | return redirect(url_for('index'))
55 | return render_template('login.html', form=form)
56 |
57 |
58 | if __name__ == '__main__':
59 | app.run()
60 |
--------------------------------------------------------------------------------
/forms/form_from_model.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | forms.form_from_model
4 | ~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Automatically create a WTForms Form from model
7 | http://flask.pocoo.org/snippets/60/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import render_template, url_for, redirect
15 | from flaskext.wtf import Form
16 | from wtforms.ext.appengine.db import model_form
17 | from wtforms import validators
18 |
19 | from app import app
20 | from models import MyModel
21 |
22 |
23 | MyForm = model_form(MyModel, Form, field_args = {
24 | 'name' : {
25 | 'validators' : [validators.Length(max=10)]
26 | }
27 | })
28 |
29 |
30 | @app.route("/edit")
31 | def edit(id):
32 | MyForm = model_form(MyModel, Form)
33 | model = MyModel.get(id)
34 | form = MyForm(request.form, model)
35 |
36 | if form.validate_on_submit():
37 | form.populate_obj(model)
38 | model.put()
39 | flash("MyModel updated")
40 | return redirect(url_for("index"))
41 | return render_template("edit.html", form=form)
42 |
43 |
44 | if __name__ == "__main__":
45 | app.run()
46 |
--------------------------------------------------------------------------------
/forms/render_wtform_without_syntaxerr.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | forms.render_wtform_without_syntaxerr
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Render WTForm fields with html attributes that cause TemplateSyntaxErrors
7 | http://flask.pocoo.org/snippets/107/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from app import app
15 |
16 |
17 | """
18 | Suppose you had a WTForm TextField that you wanted to use a javascript library like bootstrap-typeahead.js on. You might want the field to render as:
19 |
20 |
21 |
22 | After creating a WTForm in the view and passing it to your template, your first attempt would be to pass the additional keyword arguments:
23 |
24 | {{ form.myfield(name='test', data-provide='typeahead', data-data-items='3', data-source='["x","y","z"]') }}
25 |
26 | But this will lead to a TemplateSyntaxError because a dash is the subtraction operator in Python, and we can't escape the character in a keyword argument's key.
27 |
28 | Instead, pass the HTML attributes that contain invalid syntax as an ad-hoc dictionary:
29 |
30 | {{ form.myfield(name='test', **{'data-provide':'typeahead','data-items':'3','data-source': '["x","y","z"]'}) }}
31 | """
32 |
--------------------------------------------------------------------------------
/forms/secure_redirect_back.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | forms.secure_redirect_back
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Secure Back Redirects with WTForms
7 | http://flask.pocoo.org/snippets/63/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | from urlparse import urlparse, urljoin
14 |
15 | from flask import request, url_for, redirect
16 | from flaskext.wtf import Form, TextField, HiddenField
17 |
18 | from app import app
19 |
20 |
21 | def is_safe_url(target):
22 | ref_url = urlparse(request.host_url)
23 | test_url = urlparse(urljoin(request.host_url, target))
24 | return test_url.scheme in ('http', 'https') and \
25 | ref_url.netloc == test_url.netloc
26 |
27 |
28 | def get_redirect_target():
29 | for target in request.args.get('next'), request.referrer:
30 | if not target:
31 | continue
32 | if is_safe_url(target):
33 | return target
34 |
35 |
36 | class RedirectForm(Form):
37 | next = HiddenField()
38 |
39 | def __init__(self, *args, **kwargs):
40 | Form.__init__(self, *args, **kwargs)
41 | if not self.next.data:
42 | self.next.data = get_redirect_target() or ''
43 |
44 | def redirect(self, endpoint='index', **values):
45 | if is_safe_url(self.next.data):
46 | return redirect(self.next.data)
47 | target = get_redirect_target()
48 | return redirect(target or url_for(endpoint, **values))
49 |
50 |
51 | class LoginForm(RedirectForm):
52 | username = TextField('Username')
53 | password = TextField('Password')
54 |
55 |
56 | @app.route('/login', methods=['GET', 'POST'])
57 | def login():
58 | form = LoginForm()
59 | if form.validate_on_submit():
60 | # do something with the form data here
61 | return form.redirect('index')
62 | return render_template('login.html', form=form)
63 |
64 |
65 | if __name__ == '__main__':
66 | app.run()
67 |
--------------------------------------------------------------------------------
/forms/validate_flatland.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | forms.validate_flatland
4 | ~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Validating a Flatland Schema
7 | http://flask.pocoo.org/snippets/72/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flatland import Form, String
15 |
16 | from app import app
17 |
18 |
19 | class SignInForm(Form):
20 | username = String
21 | password = String
22 |
23 |
24 | """
25 | The correct way to create an element instance from a Flask request is as follows:
26 |
27 | if request.method in ['POST', 'PUT']:
28 | form = SignInForm.from_flat(request.form.items(multi=True))
29 | A little wordy, so you might want to write a little helper function:
30 |
31 | def form_from_request(schema):
32 | return schema.from_flat(request.form.items(multi=True))
33 | Now you can simply do this in a view:
34 |
35 | if request.method in ['POST', 'PUT']:
36 | form = form_from_request(SignInForm)
37 | An alternative could be to subclass Form and add a validate_on_submit method similar to what Flask-WTF does, so that you can refactor out the request.method check.
38 | """
39 |
--------------------------------------------------------------------------------
/internationalizatioin/babel_lazyproxy.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | internationalizatioin.babel_lazyproxy
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Using Babel's LazyProxy with gettext
7 | http://flask.pocoo.org/snippets/4/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from wtforms import Form, fields
15 | from myapp.utils import ugettext_lazy as _
16 | from flask import g
17 | from babel.support import LazyProxy
18 |
19 | from app import app
20 |
21 |
22 | class MyForm(Form):
23 | name = fields.TextField(_("Name"))
24 |
25 |
26 | def ugettext(s):
27 | # we assume a before_request function
28 | # assigns the correct user-specific
29 | # translations
30 | return g.translations.ugettext(s)
31 |
32 |
33 | ugettext_lazy = LazyProxy(ugettext)
34 |
35 |
36 | @app.route('/')
37 | def index():
38 | return 'index'
39 |
40 |
41 | if __name__ == "__main__":
42 | app.run()
43 |
--------------------------------------------------------------------------------
/javascript/filter_for_timeago.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | javascript.timeago_filter
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | A Filter for the jQuery Timeago Plugin
7 | http://flask.pocoo.org/snippets/49/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response
15 |
16 | from app import app
17 |
18 |
19 | """
20 | Timeago is a jQuery plugin that makes it easy to support automatically
21 | updating fuzzy timestamps (e.g. “4 minutes ago” or “about 1 day ago”).
22 | It automatically keeps them updated and only needs a very basic span
23 | tag or something similar with a certain class and title attribute.
24 |
25 | For instance
26 | ...
27 | turns into something like this:
28 | 2 years ago
29 | """
30 |
31 |
32 | @app.template_filter()
33 | def datetimeformat(datetime, timeago=True):
34 | readable = datetime.strftime('%Y-%m-%d @ %H:%M')
35 | if not timeago:
36 | return readable
37 | iso_format = datetime.strftime('%Y-%m-%dT%H:%M:%SZ')
38 | return '%s' % (
39 | iso_format,
40 | readable
41 | )
42 |
43 |
44 | """
45 | Usage:
46 | Date: {{ the_date|datetimeformat }}
47 |
48 | $(function() {
49 | $('span.timeago').timeago();
50 | });
51 | """
52 |
53 |
54 | @app.route('/')
55 | def index():
56 | return 'index'
57 |
58 |
59 | if __name__ == "__main__":
60 | app.run()
61 |
--------------------------------------------------------------------------------
/javascript/push_notifications.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | javascript.push
4 | ~~~~~~~~~~~~~~~
5 |
6 | Push Notifications with socket.io and Juggernaut
7 | http://flask.pocoo.org/snippets/80/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request
15 | from juggernaut import Juggernaut
16 |
17 | from app import app
18 |
19 |
20 | """
21 | $ npm install -g juggernaut
22 | $ juggernaut
23 | $ pip install juggernaut
24 |
25 |
26 |
32 | """
33 |
34 |
35 | @app.route('/')
36 | def index():
37 | return 'index'
38 |
39 |
40 | @app.route('/publish/')
41 | def publish():
42 | jug = Juggernaut()
43 | jug.publish('channel', 'The message')
44 |
45 |
46 | if __name__ == "__main__":
47 | app.run()
48 |
--------------------------------------------------------------------------------
/javascript/realtime_using_sse.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | javascript.realtime_sse
4 | ~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Realtime server using the SSE protocol
7 | http://flask.pocoo.org/snippets/116/
8 | """
9 | # Make sure your gevent version is >= 1.0
10 |
11 | import os
12 | import sys
13 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
14 | import time
15 |
16 | from flask import request, Response
17 | import gevent
18 | from gevent.wsgi import WSGIServer
19 | from gevent.queue import Queue
20 |
21 | from app import app
22 |
23 |
24 | # SSE "protocol" is described here: http://mzl.la/UPFyxY
25 | class ServerSentEvent(object):
26 |
27 | def __init__(self, data):
28 | self.data = data
29 | self.event = None
30 | self.id = None
31 | self.desc_map = {
32 | self.data: "data",
33 | self.event: "event",
34 | self.id: "id"
35 | }
36 |
37 | def encode(self):
38 | if not self.data:
39 | return ""
40 | lines = ["%s: %s" % (v, k) for k, v in self.desc_map.iteritems() if k]
41 | return "%s\n\n" % "\n".join(lines)
42 |
43 |
44 | subscriptions = []
45 |
46 |
47 | # Client code consumes like this.
48 | @app.route('/')
49 | def index():
50 | debug_template = """
51 |
52 |
53 |
54 |
55 | Server sent events
56 |
57 |
68 |
69 |
70 | """
71 | return(debug_template)
72 |
73 |
74 | @app.route("/debug")
75 | def debug():
76 | return "Currently %d subscriptions" % len(subscriptions)
77 |
78 |
79 | @app.route("/publish")
80 | def publish():
81 | #Dummy data - pick up from request for real data
82 | def notify():
83 | msg = str(time.time())
84 | for sub in subscriptions[:]:
85 | sub.put(msg)
86 |
87 | gevent.spawn(notify)
88 |
89 | return "OK"
90 |
91 |
92 | @app.route("/subscribe")
93 | def subscribe():
94 | def gen():
95 | q = Queue()
96 | subscriptions.append(q)
97 | try:
98 | while True:
99 | result = q.get()
100 | ev = ServerSentEvent(str(result))
101 | yield ev.encode()
102 | except GeneratorExit: # Or maybe use flask signals
103 | subscriptions.remove(q)
104 |
105 | return Response(gen(), mimetype="text/event-stream")
106 |
107 |
108 | if __name__ == "__main__":
109 | server = WSGIServer(("", 5000), app)
110 | server.serve_forever()
111 | # Then visit http://localhost:5000 to subscribe
112 | # and send messages by visiting http://localhost:5000/publish
113 |
--------------------------------------------------------------------------------
/performance/add_caching.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | performance.caching
4 | ~~~~~~~~~~~~~~~~~~~
5 |
6 | Adding caching to Flask apps
7 | http://flask.pocoo.org/snippets/9/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from werkzeug.contrib.cache import SimpleCache
15 | from flask import request
16 |
17 | from app import app
18 |
19 |
20 | CACHE_TIMEOUT = 300
21 |
22 |
23 | cache = SimpleCache()
24 |
25 |
26 | class cached(object):
27 |
28 | def __init__(self, timeout=None):
29 | self.timeout = timeout or CACHE_TIMEOUT
30 |
31 | def __call__(self, f):
32 | def decorator(*args, **kwargs):
33 | response = cache.get(request.path)
34 | if response is None:
35 | response = f(*args, **kwargs)
36 | cache.set(request.path, response, self.timeout)
37 | return response
38 | return decorator
39 |
40 |
41 | @app.route('/')
42 | # @cached()
43 | def index():
44 | return 'index'
45 |
46 |
47 | @app.before_request
48 | def return_cached():
49 | # if GET and POST not empty
50 | if not request.values:
51 | response = cache.get(request.path)
52 | if response:
53 | return response
54 |
55 |
56 | @app.after_request
57 | def cache_response(response):
58 | if not request.values:
59 | cache.set(request.path, response, CACHE_TIMEOUT)
60 | return response
61 |
62 |
63 | if __name__ == "__main__":
64 | app.run()
65 |
--------------------------------------------------------------------------------
/performance/sqlite_cache.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | performance.sqlite_cache
4 | ~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Cache implementation using SQLite
7 | http://flask.pocoo.org/snippets/87/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | import os, errno, sqlite3
15 | from time import sleep, time
16 | from cPickle import loads, dumps
17 | try:
18 | from thread import get_ident
19 | except ImportError:
20 | from dummy_thread import get_ident
21 | from werkzeug.contrib.cache import BaseCache
22 |
23 | from app import app
24 |
25 |
26 | class SqliteCache(BaseCache):
27 |
28 | _create_sql = (
29 | 'CREATE TABLE IF NOT EXISTS bucket '
30 | '('
31 | ' key TEXT PRIMARY KEY,'
32 | ' val BLOB,'
33 | ' exp FLOAT'
34 | ')'
35 | )
36 | _get_sql = 'SELECT val, exp FROM bucket WHERE key = ?'
37 | _del_sql = 'DELETE FROM bucket WHERE key = ?'
38 | _set_sql = 'REPLACE INTO bucket (key, val, exp) VALUES (?, ?, ?)'
39 | _add_sql = 'INSERT INTO bucket (key, val, exp) VALUES (?, ?, ?)'
40 |
41 | def __init__(self, path, default_timeout=300):
42 | self.path = os.path.abspath(path)
43 | try:
44 | os.mkdir(self.path)
45 | except OSError, e:
46 | if e.errno != errno.EEXIST or not os.path.isdir(self.path):
47 | raise
48 | self.default_timeout = default_timeout
49 | self.connection_cache = {}
50 |
51 | def _get_conn(self, key):
52 | key = dumps(key, 0)
53 | t_id = get_ident()
54 | if t_id not in self.connection_cache:
55 | self.connection_cache[t_id] = {}
56 | if key not in self.connection_cache[t_id]:
57 | bucket_name = str(hash(key))
58 | bucket_path = os.path.join(self.path, bucket_name)
59 | conn = sqlite3.Connection(bucket_path, timeout=60)
60 | with conn:
61 | conn.execute(self._create_sql)
62 | self.connection_cache[t_id][key] = conn
63 | return self.connection_cache[t_id][key]
64 |
65 | def get(self, key):
66 | rv = None
67 | with self._get_conn(key) as conn:
68 | for row in conn.execute(self._get_sql, (key,)):
69 | expire = row[1]
70 | if expire > time():
71 | rv = loads(str(row[0]))
72 | break
73 | return rv
74 |
75 | def delete(self, key):
76 | with self._get_conn(key) as conn:
77 | conn.execute(self._del_sql, (key,))
78 |
79 | def set(self, key, value, timeout=None):
80 | if not timeout:
81 | timeout = self.default_timeout
82 | value = buffer(dumps(value, 2))
83 | expire = time() + timeout
84 | with self._get_conn(key) as conn:
85 | conn.execute(self._set_sql, (key, value, expire))
86 |
87 | def add(self, key, value, timeout=None):
88 | if not timeout:
89 | timeout = self.default_timeout
90 | expire = time() + timeout
91 | value = buffer(dumps(value, 2))
92 | with self._get_conn(key) as conn:
93 | try:
94 | conn.execute(self._add_sql, (key, value, expire))
95 | except sqlite3.IntegrityError:
96 | pass
97 |
98 | def clear(self):
99 | for bucket in os.listdir(self.path):
100 | os.unlink(os.path.join(self.path, bucket))
101 |
102 |
103 | @app.route('/')
104 | def index():
105 | return 'index'
106 |
107 |
108 | if __name__ == "__main__":
109 | app.run()
110 |
--------------------------------------------------------------------------------
/security/csrf_protect.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | security.csrf
4 | ~~~~~~~~~~~~~
5 |
6 | CSRF Protection
7 | http://flask.pocoo.org/snippets/3/
8 | """
9 |
10 | import os
11 | import sys
12 | from uuid import uuid4
13 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
14 |
15 | from flask import request, session, abort
16 | from flask import render_template_string
17 |
18 | from app import app
19 |
20 |
21 | @app.before_request
22 | def csrf_protect():
23 | if request.method == "POST":
24 | token = session.pop('_csrf_token', None)
25 | if not token or token != request.form.get('_csrf_token'):
26 | abort(403)
27 |
28 |
29 | def generate_csrf_token():
30 | if '_csrf_token' not in session:
31 | session['_csrf_token'] = str(uuid4())
32 | return session['_csrf_token']
33 |
34 | app.jinja_env.globals['csrf_token'] = generate_csrf_token
35 |
36 |
37 | @app.route('/', methods=["GET", "POST"])
38 | def index():
39 | return render_template_string('')
40 |
41 |
42 | if __name__ == "__main__":
43 | app.run()
44 |
--------------------------------------------------------------------------------
/security/redirect_back.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | security.rback
4 | ~~~~~~~~~~~~~~
5 |
6 | Securely Redirect Back
7 | http://flask.pocoo.org/snippets/62/
8 | """
9 |
10 | import os
11 | import sys
12 | from urlparse import urlparse, urljoin
13 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
14 |
15 | from flask import request, url_for, redirect
16 | from flask import render_template_string
17 |
18 | from app import app
19 |
20 |
21 | def is_safe_url(target):
22 | ref_url = urlparse(request.host_url)
23 | test_url = urlparse(urljoin(request.host_url, target))
24 | return test_url.scheme in ('http', 'https') and \
25 | ref_url.netloc == test_url.netloc
26 |
27 |
28 | def get_redirect_target():
29 | for target in request.values.get('next'), request.referrer:
30 | if not target:
31 | continue
32 | if is_safe_url(target):
33 | return target
34 |
35 |
36 | def redirect_back(endpoint, **values):
37 | target = request.form['next']
38 | if not target or not is_safe_url(target):
39 | target = url_for(endpoint, **values)
40 | return redirect(target)
41 |
42 |
43 | @app.route('/')
44 | def index():
45 | return 'index'
46 |
47 |
48 | @app.route('/fsp')
49 | def fsp():
50 | return 'fsp'
51 |
52 |
53 | @app.route('/login', methods=['GET', 'POST'])
54 | def login():
55 | next = get_redirect_target()
56 | html_content = """
57 |
68 | """
69 | if request.method == 'POST':
70 | # Login code here
71 | return redirect_back('index')
72 | return render_template_string(html_content, next=next)
73 |
74 |
75 | if __name__ == "__main__":
76 | app.run()
77 |
--------------------------------------------------------------------------------
/security/salted_password.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | security.salted
4 | ~~~~~~~~~~~~~~~
5 |
6 | Salted Passwords
7 | http://flask.pocoo.org/snippets/54/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from werkzeug.security import generate_password_hash, check_password_hash
15 |
16 | from app import app
17 |
18 |
19 | class User(object):
20 |
21 | def __init__(self, username, password):
22 | self.username = username
23 | self.set_password(password)
24 |
25 | def set_password(self, password):
26 | self.pw_hash = generate_password_hash(password)
27 |
28 | def check_password(self, password):
29 | return check_password_hash(self.pw_hash, password)
30 |
31 |
32 | @app.route('/')
33 | def index():
34 | me = User('John Doe', 'default')
35 | print me.pw_hash
36 | print me.check_password('default')
37 | print me.check_password('defaultx')
38 | return 'index'
39 |
40 |
41 | if __name__ == "__main__":
42 | app.run()
43 |
--------------------------------------------------------------------------------
/security/serve_https.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | security.https
4 | ~~~~~~~~~~~~~~
5 |
6 | How to serve HTTPS *directly* from Flask
7 | http://flask.pocoo.org/snippets/111/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from OpenSSL import SSL
15 |
16 | from app import app
17 |
18 |
19 | context = SSL.Context(SSL.SSLv23_METHOD)
20 | context.use_privatekey_file('yourserver.key')
21 | context.use_certificate_file('yourserver.crt')
22 |
23 |
24 | @app.route('/')
25 | def index():
26 | return 'index'
27 |
28 |
29 | """
30 | Linux-related:
31 | there is a confirmed bug in pyOpenSSL that generates a runtime error:
32 | https://bugs.launchpad.net/pyopenssl/+bug/900792
33 |
34 | The workaround is to put these 2 lines in werkzeug/serving.py
35 |
36 | in class BaseWSGIServer(HTTPServer, object):
37 | ...
38 | def shutdown_request(self,request):
39 | request.shutdown()
40 | """
41 |
42 |
43 | if __name__ == "__main__":
44 | app.run(ssl_context=context)
45 |
--------------------------------------------------------------------------------
/sessions/beaker_session.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | sessions.beaker_session
4 | ~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Using Beaker session with Flask
7 | http://flask.pocoo.org/snippets/61/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request
15 | from beaker.middleware import SessionMiddleware
16 |
17 | from app import app
18 |
19 |
20 | session_opts = {
21 | 'session.type': 'ext:memcached',
22 | 'session.url': '127.0.0.1:11211',
23 | 'session.data_dir': './cache',
24 | }
25 |
26 |
27 | @app.route('/')
28 | def index():
29 | session = request.environ['beaker.session']
30 | if not session.has_key('value'):
31 | session['value'] = 'Save in session'
32 | session.save()
33 | return "Session value set."
34 | else:
35 | return session['value']
36 |
37 | if __name__ == '__main__':
38 | app.wsgi_app = SessionMiddleware(app.wsgi_app, session_opts)
39 | app.run(debug=True)
40 |
--------------------------------------------------------------------------------
/sessions/better_client_session.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | sessions.better_client_session
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Better Client-side sessions
7 | http://flask.pocoo.org/snippets/51/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from werkzeug.datastructures import CallbackDict
15 | from flask.sessions import SessionInterface, SessionMixin
16 | from itsdangerous import URLSafeTimedSerializer, BadSignature
17 |
18 | from app import app
19 |
20 |
21 | class ItsdangerousSession(CallbackDict, SessionMixin):
22 |
23 | def __init__(self, initial=None):
24 | def on_update(self):
25 | self.modified = True
26 | CallbackDict.__init__(self, initial, on_update)
27 | self.modified = False
28 |
29 |
30 | class ItsdangerousSessionInterface(SessionInterface):
31 | salt = 'cookie-session'
32 | session_class = ItsdangerousSession
33 |
34 | def get_serializer(self, app):
35 | if not app.secret_key:
36 | return None
37 | return URLSafeTimedSerializer(app.secret_key,
38 | salt=self.salt)
39 |
40 | def open_session(self, app, request):
41 | s = self.get_serializer(app)
42 | if s is None:
43 | return None
44 | val = request.cookies.get(app.session_cookie_name)
45 | if not val:
46 | return self.session_class()
47 | max_age = app.permanent_session_lifetime.total_seconds()
48 | try:
49 | data = s.loads(val, max_age=max_age)
50 | return self.session_class(data)
51 | except BadSignature:
52 | return self.session_class()
53 |
54 | def save_session(self, app, session, response):
55 | domain = self.get_cookie_domain(app)
56 | if not session:
57 | if session.modified:
58 | response.delete_cookie(app.session_cookie_name,
59 | domain=domain)
60 | return
61 | expires = self.get_expiration_time(app, session)
62 | val = self.get_serializer(app).dumps(dict(session))
63 | response.set_cookie(app.session_cookie_name, val,
64 | expires=expires, httponly=True,
65 | domain=domain)
66 |
67 |
68 | app.session_interface = ItsdangerousSessionInterface()
69 |
--------------------------------------------------------------------------------
/sessions/count_online_users.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | sessions.count_online_users
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Counting Online Users with Redis
7 | http://flask.pocoo.org/snippets/71/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | import time
14 | from datetime import datetime
15 |
16 | from redis import Redis
17 | from flask import Response, request
18 |
19 | from app import app
20 |
21 |
22 | redis = Redis()
23 | ONLINE_LAST_MINUTES = 5
24 | app.config['ONLINE_LAST_MINUTES'] = ONLINE_LAST_MINUTES
25 |
26 |
27 | def mark_online(user_id):
28 | now = int(time.time())
29 | expires = now + (app.config['ONLINE_LAST_MINUTES'] * 60) + 10
30 | all_users_key = 'online-users/%d' % (now // 60)
31 | user_key = 'user-activity/%s' % user_id
32 | p = redis.pipeline()
33 | p.sadd(all_users_key, user_id)
34 | p.set(user_key, now)
35 | p.expireat(all_users_key, expires)
36 | p.expireat(user_key, expires)
37 | p.execute()
38 |
39 |
40 | def get_user_last_activity(user_id):
41 | last_active = redis.get('user-activity/%s' % user_id)
42 | if last_active is None:
43 | return None
44 | return datetime.utcfromtimestamp(int(last_active))
45 |
46 |
47 | def get_online_users():
48 | current = int(time.time()) // 60
49 | minutes = xrange(app.config['ONLINE_LAST_MINUTES'])
50 | return redis.sunion(['online-users/%d' % (current - x)
51 | for x in minutes])
52 |
53 |
54 | @app.before_request
55 | def mark_current_user_online():
56 | mark_online(request.remote_addr)
57 |
58 |
59 | @app.route('/online')
60 | def index():
61 | return Response('Online: %s' % ', '.join(get_online_users()),
62 | mimetype='text/plain')
63 |
64 |
65 | if __name__ == '__main__':
66 | app.run()
67 |
--------------------------------------------------------------------------------
/sessions/file_session.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | sessions.file_session
4 | ~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Generic server-based sessions (file-system, etc)
7 | http://flask.pocoo.org/snippets/109/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | import cPickle as pickle
14 |
15 | import base64
16 | import hmac
17 | import hashlib
18 | import random
19 | import string
20 |
21 | import datetime
22 | from uuid import uuid4
23 | from collections import OrderedDict
24 |
25 | from werkzeug.datastructures import CallbackDict
26 | from flask.sessions import SessionInterface, SessionMixin
27 |
28 | from app import app
29 |
30 |
31 | def _generate_sid():
32 | return str(uuid4())
33 |
34 |
35 | def _calc_hmac(body, secret):
36 | return base64.b64encode(hmac.new(secret, body, hashlib.sha1).digest())
37 |
38 |
39 | class ManagedSession(CallbackDict, SessionMixin):
40 | def __init__(self, initial=None, sid=None, new=False, randval=None, hmac_digest=None):
41 | def on_update(self):
42 | self.modified = True
43 |
44 | CallbackDict.__init__(self, initial, on_update)
45 | self.sid = sid
46 | self.new = new
47 | self.modified = False
48 | self.randval = randval
49 | self.hmac_digest = hmac_digest
50 |
51 | def sign(self, secret):
52 | if not self.hmac_digest:
53 | self.randval = ''.join(random.sample(string.lowercase+string.digits, 20))
54 | self.hmac_digest = _calc_hmac('%s:%s' % (self.sid, self.randval), secret)
55 |
56 |
57 | class SessionManager(object):
58 | def new_session(self):
59 | 'Create a new session'
60 | raise NotImplementedError
61 |
62 | def exists(self, sid):
63 | 'Does the given session-id exist?'
64 | raise NotImplementedError
65 |
66 | def remove(self, sid):
67 | 'Remove the session'
68 | raise NotImplementedError
69 |
70 | def get(self, sid, digest):
71 | 'Retrieve a managed session by session-id, checking the HMAC digest'
72 | raise NotImplementedError
73 |
74 | def put(self, session):
75 | 'Store a managed session'
76 | raise NotImplementedError
77 |
78 |
79 | class CachingSessionManager(SessionManager):
80 | def __init__(self, parent, num_to_store):
81 | self.parent = parent
82 | self.num_to_store = num_to_store
83 | self._cache = OrderedDict()
84 |
85 | def _normalize(self):
86 | print "Session cache size: %s" % len(self._cache)
87 | if len(self._cache) > self.num_to_store:
88 | while len(self._cache) > (self.num_to_store * 0.8): # flush 20% of the cache
89 | self._cache.popitem(False)
90 |
91 | def new_session(self):
92 | session = self.parent.new_session()
93 | self._cache[session.sid] = session
94 | self._normalize()
95 | return session
96 |
97 | def remove(self, sid):
98 | self.parent.remove(sid)
99 | if sid in self._cache:
100 | del self._cache[sid]
101 |
102 | def exists(self, sid):
103 | if sid in self._cache:
104 | return True
105 | return self.parent.exists(sid)
106 |
107 | def get(self, sid, digest):
108 | session = None
109 | if sid in self._cache:
110 | session = self._cache[sid]
111 | if session.hmac_digest != digest:
112 | session = None
113 |
114 | # reset order in OrderedDict
115 | del self._cache[sid]
116 |
117 | if not session:
118 | session = self.parent.get(sid, digest)
119 |
120 | self._cache[sid] = session
121 | self._normalize()
122 | return session
123 |
124 | def put(self, session):
125 | self.parent.put(session)
126 | if session.sid in self._cache:
127 | del self._cache[session.sid]
128 | self._cache[session.sid] = session
129 | self._normalize()
130 |
131 |
132 | class FileBackedSessionManager(SessionManager):
133 | def __init__(self, path, secret):
134 | self.path = path
135 | self.secret = secret
136 | if not os.path.exists(self.path):
137 | os.makedirs(self.path)
138 |
139 | def exists(self, sid):
140 | fname = os.path.join(self.path, sid)
141 | return os.path.exists(fname)
142 |
143 | def remove(self, sid):
144 | print 'Removing session: %s' % sid
145 | fname = os.path.join(self.path, sid)
146 | if os.path.exists(fname):
147 | os.unlink(fname)
148 |
149 | def new_session(self):
150 | sid = _generate_sid()
151 | fname = os.path.join(self.path, sid)
152 |
153 | while os.path.exists(fname):
154 | sid = _generate_sid()
155 | fname = os.path.join(self.path, sid)
156 |
157 | # touch the file
158 | with open(fname, 'w'):
159 | pass
160 |
161 | print "Created new session: %s" % sid
162 |
163 | return ManagedSession(sid=sid)
164 |
165 | def get(self, sid, digest):
166 | 'Retrieve a managed session by session-id, checking the HMAC digest'
167 |
168 | print "Looking for session: %s, %s" % (sid, digest)
169 |
170 | fname = os.path.join(self.path, sid)
171 | data = None
172 | hmac_digest = None
173 | randval = None
174 |
175 | if os.path.exists(fname):
176 | try:
177 | with open(fname) as f:
178 | randval, hmac_digest, data = pickle.load(f)
179 | except:
180 | print "Error loading session file"
181 |
182 | if not data:
183 | print "Missing data?"
184 | return self.new_session()
185 |
186 | # This assumes the file is correct, if you really want to
187 | # make sure the session is good from the server side, you
188 | # can re-calculate the hmac
189 |
190 | if hmac_digest != digest:
191 | print "Invalid HMAC for session"
192 | return self.new_session()
193 |
194 | return ManagedSession(data, sid=sid, randval=randval, hmac_digest=hmac_digest)
195 |
196 | def put(self, session):
197 | 'Store a managed session'
198 | print "Storing session: %s" % session.sid
199 |
200 | if not session.hmac_digest:
201 | session.sign(self.secret)
202 |
203 | fname = os.path.join(self.path, session.sid)
204 | with open(fname, 'w') as f:
205 | pickle.dump((session.randval, session.hmac_digest, dict(session)), f)
206 |
207 |
208 | class ManagedSessionInterface(SessionInterface):
209 | def __init__(self, manager, skip_paths, cookie_timedelta):
210 | self.manager = manager
211 | self.skip_paths = skip_paths
212 | self.cookie_timedelta = cookie_timedelta
213 |
214 | def get_expiration_time(self, app, session):
215 | if session.permanent:
216 | return app.permanent_session_lifetime
217 | return datetime.datetime.now() + self.cookie_timedelta
218 |
219 | def open_session(self, app, request):
220 | cookie_val = request.cookies.get(app.session_cookie_name)
221 |
222 | if not cookie_val or not '!' in cookie_val:
223 | # Don't bother creating a cookie for static resources
224 | for sp in self.skip_paths:
225 | if request.path.startswith(sp):
226 | return None
227 |
228 | print 'Missing cookie'
229 | return self.manager.new_session()
230 |
231 | sid, digest = cookie_val.split('!', 1)
232 |
233 | if self.manager.exists(sid):
234 | return self.manager.get(sid, digest)
235 |
236 | return self.manager.new_session()
237 |
238 | def save_session(self, app, session, response):
239 | domain = self.get_cookie_domain(app)
240 | if not session:
241 | self.manager.remove(session.sid)
242 | if session.modified:
243 | response.delete_cookie(app.session_cookie_name, domain=domain)
244 | return
245 |
246 | if not session.modified:
247 | # no need to save an unaltered session
248 | # TODO: put logic here to test if the cookie is older than N days, if so, update the expiration date
249 | return
250 |
251 | self.manager.put(session)
252 | session.modified = False
253 |
254 | cookie_exp = self.get_expiration_time(app, session)
255 | response.set_cookie(app.session_cookie_name,
256 | '%s!%s' % (session.sid, session.hmac_digest),
257 | expires=cookie_exp, httponly=True, domain=domain)
258 |
259 |
260 | app.session_interface = ManagedSessionInterface(CachingSessionManager(FileBackedSessionManager(app.config['SESSION_PATH'], app.config['SECRET_KEY']), 1000), skip_paths, datetime.timedelta(days=1))
261 |
--------------------------------------------------------------------------------
/sessions/mongodb_session.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | sessions.mongodb_session
4 | ~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Server-side sessions with MongoDB (pymongo)
7 | http://flask.pocoo.org/snippets/110/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | from uuid import uuid4
14 | from datetime import datetime, timedelta
15 |
16 | from flask.sessions import SessionInterface, SessionMixin
17 | from werkzeug.datastructures import CallbackDict
18 | from pymongo import MongoClient
19 |
20 | from app import app
21 |
22 |
23 | class MongoSession(CallbackDict, SessionMixin):
24 |
25 | def __init__(self, initial=None, sid=None):
26 | CallbackDict.__init__(self, initial)
27 | self.sid = sid
28 | self.modified = False
29 |
30 |
31 | class MongoSessionInterface(SessionInterface):
32 |
33 | def __init__(self, host='localhost', port=27017,
34 | db='', collection='sessions'):
35 | client = MongoClient(host, port)
36 | self.store = client[db][collection]
37 |
38 | def open_session(self, app, request):
39 | sid = request.cookies.get(app.session_cookie_name)
40 | if sid:
41 | stored_session = self.store.find_one({'sid': sid})
42 | if stored_session:
43 | if stored_session.get('expiration') > datetime.utcnow():
44 | return MongoSession(initial=stored_session['data'],
45 | sid=stored_session['sid'])
46 | sid = str(uuid4())
47 | return MongoSession(sid=sid)
48 |
49 | def save_session(self, app, session, response):
50 | domain = self.get_cookie_domain(app)
51 | if not session:
52 | response.delete_cookie(app.session_cookie_name, domain=domain)
53 | return
54 | if self.get_expiration_time(app, session):
55 | expiration = self.get_expiration_time(app, session)
56 | else:
57 | expiration = datetime.utcnow() + timedelta(hours=1)
58 | self.store.update({'sid': session.sid},
59 | {'sid': session.sid,
60 | 'data': session,
61 | 'expiration': expiration}, True)
62 | response.set_cookie(app.session_cookie_name, session.sid,
63 | expires=self.get_expiration_time(app, session),
64 | httponly=True, domain=domain)
65 |
66 |
67 | app.session_interface = MongoSessionInterface(db='pjuu')
68 |
--------------------------------------------------------------------------------
/sessions/old_new_session.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | sessions.old_new_session
4 | ~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Support for Old and New Sessions
7 | http://flask.pocoo.org/snippets/52/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | try:
14 | from flask.sessions import SessionMixin, SessionInterface
15 | except ImportError:
16 | class SessionInterface(object):
17 | pass
18 |
19 | class SessionMixin(object):
20 | def _get_permanent(self):
21 | return self.get('_permanent', False)
22 | def _set_permanent(self, value):
23 | self['_permanent'] = bool(value)
24 | permanent = property(_get_permanent, _set_permanent)
25 | del _get_permanent, _set_permanent
26 |
27 | # you can use a werkzeug.datastructure.CallbackDict
28 | # to automatically update modified if you want, but
29 | # it's not a requirement.
30 | new = False
31 | modified = True
32 |
33 |
34 | class MySession(dict, SessionMixin):
35 | pass
36 |
37 |
38 | class MySessionInterface(object):
39 |
40 | def open_session(self, app, request):
41 | # load the session and return it.
42 | return MySession()
43 |
44 | def save_session(self, app, session, response):
45 | # save the session
46 | ...
47 |
48 |
49 | def init_my_extension(app):
50 | if not hasattr(app, 'session_interface'):
51 | app.open_session = lambda r: \
52 | app.session_interface.open_session(app, r)
53 | app.save_session = lambda s, r: \
54 | app.session_interface.save_session(app, s, r)
55 | app.session_interface = MySessionInterface()
56 |
--------------------------------------------------------------------------------
/sessions/redis_session.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | sessions.redis_session
4 | ~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Server-side Sessions with Redis
7 | http://flask.pocoo.org/snippets/75/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | import pickle
14 | from datetime import timedelta
15 | from uuid import uuid4
16 | from redis import Redis
17 | from werkzeug.datastructures import CallbackDict
18 | from flask.sessions import SessionInterface, SessionMixin
19 |
20 | from app import app
21 |
22 |
23 | class RedisSession(CallbackDict, SessionMixin):
24 |
25 | def __init__(self, initial=None, sid=None, new=False):
26 | def on_update(self):
27 | self.modified = True
28 | CallbackDict.__init__(self, initial, on_update)
29 | self.sid = sid
30 | self.new = new
31 | self.modified = False
32 |
33 |
34 | class RedisSessionInterface(SessionInterface):
35 | serializer = pickle
36 | session_class = RedisSession
37 |
38 | def __init__(self, redis=None, prefix='session:'):
39 | if redis is None:
40 | redis = Redis()
41 | self.redis = redis
42 | self.prefix = prefix
43 |
44 | def generate_sid(self):
45 | return str(uuid4())
46 |
47 | def get_redis_expiration_time(self, app, session):
48 | if session.permanent:
49 | return app.permanent_session_lifetime
50 | return timedelta(days=1)
51 |
52 | def open_session(self, app, request):
53 | sid = request.cookies.get(app.session_cookie_name)
54 | if not sid:
55 | sid = self.generate_sid()
56 | return self.session_class(sid=sid, new=True)
57 | val = self.redis.get(self.prefix + sid)
58 | if val is not None:
59 | data = self.serializer.loads(val)
60 | return self.session_class(data, sid=sid)
61 | return self.session_class(sid=sid, new=True)
62 |
63 | def save_session(self, app, session, response):
64 | domain = self.get_cookie_domain(app)
65 | if not session:
66 | self.redis.delete(self.prefix + session.sid)
67 | if session.modified:
68 | response.delete_cookie(app.session_cookie_name,
69 | domain=domain)
70 | return
71 | redis_exp = self.get_redis_expiration_time(app, session)
72 | cookie_exp = self.get_expiration_time(app, session)
73 | val = self.serializer.dumps(dict(session))
74 | self.redis.setex(self.prefix + session.sid, val,
75 | int(redis_exp.total_seconds()))
76 | response.set_cookie(app.session_cookie_name, session.sid,
77 | expires=cookie_exp, httponly=True,
78 | domain=domain)
79 |
80 |
81 | app.session_interface = RedisSessionInterface()
82 |
83 |
84 | """
85 | def total_seconds(td):
86 | return td.days * 60 * 60 * 24 + td.seconds
87 | """
88 |
--------------------------------------------------------------------------------
/sessions/sqlite_session.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | sessions.sqlite_session
4 | ~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Server-side sessions with SQLite
7 | http://flask.pocoo.org/snippets/86/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | import errno, sqlite3
14 | from uuid import uuid4
15 | from cPickle import dumps, loads
16 | from collections import MutableMapping
17 | from flask.sessions import SessionInterface, SessionMixin
18 |
19 | from app import app
20 |
21 |
22 | class SqliteSession(MutableMapping, SessionMixin):
23 |
24 | _create_sql = (
25 | 'CREATE TABLE IF NOT EXISTS session '
26 | '('
27 | ' key TEXT PRIMARY KEY,'
28 | ' val BLOB'
29 | ')'
30 | )
31 | _get_sql = 'SELECT val FROM session WHERE key = ?'
32 | _set_sql = 'REPLACE INTO session (key, val) VALUES (?, ?)'
33 | _del_sql = 'DELETE FROM session WHERE key = ?'
34 | _ite_sql = 'SELECT key FROM session'
35 | _len_sql = 'SELECT COUNT(*) FROM session'
36 |
37 | def __init__(self, directory, sid, *args, **kwargs):
38 | self.path = os.path.join(directory, sid)
39 | self.directory = directory
40 | self.sid = sid
41 | self.modified = False
42 | self.conn = None
43 | if not os.path.exists(self.path):
44 | with self._get_conn() as conn:
45 | conn.execute(self._create_sql)
46 | self.new = True
47 |
48 | def __getitem__(self, key):
49 | key = dumps(key, 0)
50 | rv = None
51 | with self._get_conn() as conn:
52 | for row in conn.execute(self._get_sql, (key,)):
53 | rv = loads(str(row[0]))
54 | break
55 | if rv is None:
56 | raise KeyError('Key not in this session')
57 | return rv
58 |
59 | def __setitem__(self, key, value):
60 | key = dumps(key, 0)
61 | value = buffer(dumps(value, 2))
62 | with self._get_conn() as conn:
63 | conn.execute(self._set_sql, (key, value))
64 | self.modified = True
65 |
66 | def __delitem__(self, key):
67 | key = dumps(key, 0)
68 | with self._get_conn() as conn:
69 | conn.execute(self._del_sql, (key,))
70 | self.modified = True
71 |
72 | def __iter__(self):
73 | with self._get_conn() as conn:
74 | for row in conn.execute(self._ite_sql):
75 | yield loads(str(row[0]))
76 |
77 | def __len__(self):
78 | with self._get_conn() as conn:
79 | for row in conn.execute(self._len_sql):
80 | return row[0]
81 |
82 | def _get_conn(self):
83 | if not self.conn:
84 | self.conn = sqlite3.Connection(self.path)
85 | return self.conn
86 |
87 | # These proxy classes are needed in order
88 | # for this session implementation to work properly.
89 | # That is because sometimes flask will chain method calls
90 | # with session'setdefault' calls.
91 | # Eg: session.setdefault('_flashes', []).append(1)
92 | # With these proxies, the changes made by chained
93 | # method calls will be persisted back to the sqlite
94 | # database.
95 | class CallableAttributeProxy(object):
96 | def __init__(self, session, key, obj, attr):
97 | self.session = session
98 | self.key = key
99 | self.obj = obj
100 | self.attr = attr
101 | def __call__(self, *args, **kwargs):
102 | rv = self.attr(*args, **kwargs)
103 | self.session[self.key] = self.obj
104 | return rv
105 |
106 | class PersistedObjectProxy(object):
107 | def __init__(self, session, key, obj):
108 | self.session = session
109 | self.key = key
110 | self.obj = obj
111 | def __getattr__(self, name):
112 | attr = getattr(self.obj, name)
113 | if callable(attr):
114 | return SqliteSession.CallableAttributeProxy(
115 | self.session, self.key, self.obj, attr)
116 | return attr
117 |
118 | def setdefault(self, key, value):
119 | if key not in self:
120 | self[key] = value
121 | self.modified = True
122 | return SqliteSession.PersistedObjectProxy(
123 | self, key, self[key])
124 |
125 |
126 | class SqliteSessionInterface(SessionInterface):
127 |
128 | def __init__(self, directory):
129 | directory = os.path.abspath(directory)
130 | if not os.path.exists(directory):
131 | os.mkdir(directory)
132 | self.directory = directory
133 |
134 | def open_session(self, app, request):
135 | sid = request.cookies.get(app.session_cookie_name)
136 | if not sid:
137 | sid = str(uuid4())
138 | rv = SqliteSession(self.directory, sid)
139 | return rv
140 |
141 | def save_session(self, app, session, response):
142 | domain = self.get_cookie_domain(app)
143 | if not session:
144 | try:
145 | os.unlink(session.path)
146 | except OSError, e:
147 | if e.errno != errno.ENOENT:
148 | raise
149 | if session.modified:
150 | response.delete_cookie(app.session_cookie_name,
151 | domain=domain)
152 | return
153 | cookie_exp = self.get_expiration_time(app, session)
154 | response.set_cookie(app.session_cookie_name, session.sid,
155 | expires=cookie_exp, httponly=True, domain=domain)
156 |
157 |
158 | # Use shared memory (tmpfs) for maximum scalability
159 | # It is possible to use a NFS directory.
160 | # Recent NFS implementions have good fcntl support
161 | # which is the locking mechanism sqlite uses.
162 | path = '/run/shm/app_session'
163 | if not os.path.exists(path):
164 | os.mkdir(path)
165 | os.chmod(path, int('700', 8))
166 | app.session_interface = SqliteSessionInterface(path)
167 |
--------------------------------------------------------------------------------
/sessions/unittest_example.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | sessions.unittest_example
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Unittest example with before and after function calls
7 | http://flask.pocoo.org/snippets/58/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 |
15 | def test_set_date_range(self):
16 | arg_dict = {
17 | 'min_date': "2011-7-1",
18 | 'max_date': "2011-7-4",
19 | }
20 | with self.app.test_request_context('/date_range/',
21 | method="POST", data=arg_dict):
22 |
23 | # call the before funcs
24 | rv = self.app.preprocess_request()
25 | if rv != None:
26 | response = self.app.make_response(rv)
27 | else:
28 | # do the main dispatch
29 | rv = self.app.dispatch_request()
30 | response = self.app.make_response(rv)
31 |
32 | # now do the after funcs
33 | response = self.app.process_response(response)
34 |
35 | assert response.mimetype == 'application/json'
36 | assert "OK" in response.data
37 |
--------------------------------------------------------------------------------
/template.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | flask-snippets.template
4 | ~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Template Python file for flask-snippets.
7 | """
8 |
9 | import os
10 | import sys
11 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
12 |
13 | from flask import request, Response
14 |
15 | from app import app
16 |
17 |
18 | @app.route('/')
19 | def index():
20 | return 'index'
21 |
22 |
23 | if __name__ == "__main__":
24 | app.run()
25 |
--------------------------------------------------------------------------------
/templatetricks/enable_line_statement.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | templatetricks.enable_line_statement
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Enable jinja2 line statements
7 | http://flask.pocoo.org/snippets/101/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response
15 |
16 | from app import app
17 |
18 |
19 | app.jinja_env.line_statement_prefix = '%'
20 |
21 |
22 | @app.route('/')
23 | def index():
24 | return 'index'
25 |
26 |
27 | """
28 |
29 | % for item in items
30 | - {{ item }}
31 | % endfor
32 |
33 | """
34 |
35 |
36 | if __name__ == "__main__":
37 | app.run()
38 |
--------------------------------------------------------------------------------
/templatetricks/gae_correct_errors.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | templatetricks.gae_correct_errors
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Show correct Tracebacks for some Errors triggered inside a Template on GAE
7 | http://flask.pocoo.org/snippets/74/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | def format_exception(tb):
15 | return tb.render_as_text()
16 | # undocumented feature
17 | app.jinja_env.exception_formatter = format_exception
18 |
19 |
20 | from flask import make_response
21 | def format_exception(tb):
22 | res = make_response(tb.render_as_text())
23 | res.content_type = 'text/plain'
24 | return res
25 | app.jinja_env.exception_formatter = format_exception
26 |
--------------------------------------------------------------------------------
/templatetricks/generate_pdf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | templatetricks.generate_pdf
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Generating PDF from Flask template (using xhtml2pdf)
7 | http://flask.pocoo.org/snippets/68/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response, render_template, redirect, url_for
15 | from flaskext.mail import Mail, Message
16 | from xhtml2pdf import pisa
17 | from StringIO import StringIO
18 |
19 | from app import app
20 |
21 |
22 | html_content = """
23 |
24 |
25 |
26 |
27 | {% block body %}
28 | Some page title.
29 |
30 |
31 |
32 | Some text. |
33 |
34 |
35 |
36 |
37 |
38 | Some subtitle
39 | {{ g.user.get('user_attribute') }}
40 | |
41 |
42 |
43 |
44 |
45 |
46 | {% endblock %}
47 |
48 |
49 | """
50 |
51 |
52 | def create_pdf(pdf_data):
53 | pdf = StringIO()
54 | pisa.CreatePDF(StringIO(pdf_data.encode('utf-8')), pdf)
55 | return pdf
56 |
57 |
58 | mail_ext = Mail(app)
59 |
60 |
61 | @app.route('/your/url')
62 | def your_view():
63 | subject = "Mail with PDF"
64 | receiver = "receiver@mail.com"
65 | mail_to_be_sent = Message(subject=subject, recipients=[receiver])
66 | mail_to_be_sent.body = "This email contains PDF."
67 | pdf = create_pdf(render_template('your/template.html'))
68 | mail_to_be_sent.attach("file.pdf", "application/pdf", pdf.getvalue())
69 | mail_ext.send(mail_to_be_sent)
70 | return redirect(url_for('other_view'))
71 |
--------------------------------------------------------------------------------
/templatetricks/latex_second_jinja.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | templatetricks.latex_second_jinja
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Using a second Jinja environment for LaTeX templates.
7 | http://flask.pocoo.org/snippets/55/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response, render_template, redirect, url_for
15 |
16 | from app import app
17 |
18 |
19 | LATEX_SUBS = (
20 | (re.compile(r'\\'), r'\\textbackslash'),
21 | (re.compile(r'([{}_#%&$])'), r'\\\1'),
22 | (re.compile(r'~'), r'\~{}'),
23 | (re.compile(r'\^'), r'\^{}'),
24 | (re.compile(r'"'), r"''"),
25 | (re.compile(r'\.\.\.+'), r'\\ldots'),
26 | )
27 |
28 | def escape_tex(value):
29 | newval = value
30 | for pattern, replacement in LATEX_SUBS:
31 | newval = pattern.sub(replacement, newval)
32 | return newval
33 |
34 | texenv = app.create_jinja_environment()
35 | texenv.block_start_string = '((*'
36 | texenv.block_end_string = '*))'
37 | texenv.variable_start_string = '((('
38 | texenv.variable_end_string = ')))'
39 | texenv.comment_start_string = '((='
40 | texenv.comment_end_string = '=))'
41 | texenv.filters['escape_tex'] = escape_tex
42 |
43 |
44 | template = texenv.get_template('template.tex')
45 | template.render(name='Tom')
46 |
47 |
48 | """
49 | \documentclass{article}
50 |
51 | \begin{document}
52 | Hello, ((( name|escape_tex )))!
53 | \end{document}
54 | """
55 |
--------------------------------------------------------------------------------
/templatetricks/link_form_macro.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | templatetricks.link_form_macro
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | link_to and form_tag macros
7 | http://flask.pocoo.org/snippets/14/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from app import app
15 |
16 |
17 | """
18 | The HTML/Jinja for a link to a page on your site looks quite awkward.
19 |
20 | Link text!
21 | With this macro:
22 |
23 | {% macro link_to(endpoint, text) -%}
24 | {{ text|safe }}
25 | {%- endmacro %}
26 | The above link will become:
27 |
28 | {{ link_to('some.view', "Link text!", foo=bar) }}
29 | It's shorter and looks cleaner, especially if the content of the link is also a variable.
30 |
31 | A similar technique, using the call tag, can be used for forms:
32 |
33 | {% macro form_tag(endpoint, method='post') -%}
34 |
38 | {%- endmacro %}
39 | Then, you can create a form with:
40 |
41 | {% call form_tag('create_entry') %}
42 |
43 |
44 |
45 | {% endcall %}
46 | """
47 |
--------------------------------------------------------------------------------
/templatetricks/nl2br_filter.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | templatetricks.nl2br_filter
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | nl2br filter
7 | http://flask.pocoo.org/snippets/28/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | import re
14 |
15 | from jinja2 import evalcontextfilter, Markup, escape
16 |
17 | from app import app
18 |
19 |
20 | _paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')
21 |
22 |
23 | @app.template_filter()
24 | @evalcontextfilter
25 | def nl2br(eval_ctx, value):
26 | result = u'\n\n'.join(u'%s
' % p.replace('\n', '
\n') \
27 | for p in _paragraph_re.split(escape(value)))
28 | if eval_ctx.autoescape:
29 | result = Markup(result)
30 | return result
31 |
--------------------------------------------------------------------------------
/templatetricks/number_format.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | templatetricks.number_format
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | number_format filter
7 | http://flask.pocoo.org/snippets/29/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from app import app
15 |
16 |
17 | @app.template_filter()
18 | def number_format(value, tsep=',', dsep='.'):
19 | s = unicode(value)
20 | cnt = 0
21 | numchars = dsep + '0123456789'
22 | ls = len(s)
23 | while cnt < ls and s[cnt] not in numchars:
24 | cnt += 1
25 |
26 | lhs = s[:cnt]
27 | s = s[cnt:]
28 | if not dsep:
29 | cnt = -1
30 | else:
31 | cnt = s.rfind(dsep)
32 | if cnt > 0:
33 | rhs = dsep + s[cnt+1:]
34 | s = s[:cnt]
35 | else:
36 | rhs = ''
37 |
38 | splt = ''
39 | while s != '':
40 | splt = s[-3:] + tsep + splt
41 | s = s[:-3]
42 |
43 | return lhs + splt[:-1] + rhs
44 |
--------------------------------------------------------------------------------
/templatetricks/override_autoescaped.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | templatetricks.override_autoescaped
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Override which templates are autoescaped
7 | http://flask.pocoo.org/snippets/41/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import Flask
15 |
16 | class JHtmlEscapingFlask(Flask):
17 |
18 | def select_jinja_autoescape(self, filename):
19 | if filename.endswith('.jhtml'):
20 | return True
21 | return Flask.select_jinja_autoescape(self, filename)
22 |
23 | app = JHtmlEscapingFlask(__name__)
24 |
--------------------------------------------------------------------------------
/templatetricks/timesince_filter.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | templatetricks.timesince_filter
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | timesince filter
7 | http://flask.pocoo.org/snippets/33/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | from datetime import datetime
14 |
15 | from app import app
16 |
17 |
18 | @app.template_filter()
19 | def timesince(dt, default="just now"):
20 | """
21 | Returns string representing "time since" e.g.
22 | 3 days ago, 5 hours ago etc.
23 | """
24 |
25 | now = datetime.utcnow()
26 | diff = now - dt
27 |
28 | periods = (
29 | (diff.days / 365, "year", "years"),
30 | (diff.days / 30, "month", "months"),
31 | (diff.days / 7, "week", "weeks"),
32 | (diff.days, "day", "days"),
33 | (diff.seconds / 3600, "hour", "hours"),
34 | (diff.seconds / 60, "minute", "minutes"),
35 | (diff.seconds, "second", "seconds"),
36 | )
37 |
38 | for period, singular, plural in periods:
39 |
40 | if period:
41 | return "%d %s ago" % (period, singular if period == 1 else plural)
42 |
43 | return default
44 |
--------------------------------------------------------------------------------
/templatetricks/use_genshi.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | templatetricks.use_genshi
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Using Genshi with Flask
7 | http://flask.pocoo.org/snippets/17/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import Flask
15 | from flaskext.genshi import Genshi, render_response
16 |
17 | app = Flask(__name__)
18 | genshi = Genshi(app)
19 |
20 | @app.route('/')
21 | def index():
22 | render_response('index.html')
23 |
--------------------------------------------------------------------------------
/templatetricks/use_markdown.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | templatetricks.use_markdown
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Using the markdown language
7 | http://flask.pocoo.org/snippets/19/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import render_template_string, Markup
15 | import markdown
16 |
17 | from app import app
18 |
19 |
20 | html_content = """
21 |
22 |
23 | Markdown Snippet
24 |
25 |
26 | {{ content }}
27 |
28 |
29 | """
30 |
31 |
32 | @app.route('/')
33 | def index():
34 | content = """
35 | Chapter
36 | =======
37 |
38 | Section
39 | -------
40 |
41 | * Item 1
42 | * Item 2
43 | """
44 | content = Markup(markdown.markdown(content))
45 | return render_template_string(html_content, **locals())
46 |
47 |
48 | if __name__ == "__main__":
49 | app.run()
50 |
--------------------------------------------------------------------------------
/urls/catch_all.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | urls.catch_all
4 | ~~~~~~~~~~~~~~
5 |
6 | Catch-All URL
7 | http://flask.pocoo.org/snippets/57/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from app import app
15 |
16 |
17 | @app.route('/', defaults={'path': ''})
18 | @app.route('/')
19 | def catch_all(path):
20 | return 'You want path: %s' % path
21 |
22 |
23 | if __name__ == "__main__":
24 | app.run()
25 | """
26 | % curl 127.0.0.1:5000 # Matches the first rule
27 | % curl 127.0.0.1:5000/foo/bar # Matches the second rule
28 | """
29 |
--------------------------------------------------------------------------------
/urls/generate_sitemap.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | urls.generate_map
4 | ~~~~~~~~~~~~~~~~~
5 |
6 | Generating a sitemap.xml
7 | http://flask.pocoo.org/snippets/108/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response
15 |
16 | from app import app
17 |
18 |
19 |
20 | @sk-sqlalchemy model for User
21 | class User(db.Model, UserMixin):
22 |
23 | __tablename__ = 'users'
24 |
25 | id = Column(db.Integer, primary_key=True)
26 | name = Column(db.String(32), nullable=False, unique=True)
27 | email = Column(db.String, nullable=False, unique=True)
28 | activation_key = Column(db.String)
29 | created_time = Column(db.DateTime, default=get_current_time)
30 | modified_time = Column(db.TIMESTAMP, onupdate=get_current_time(), default=get_current_time())
31 |
32 |
33 | # a route for generating sitemap.xml
34 | @frontend.route('/sitemap.xml', methods=['GET'])
35 | def sitemap():
36 | """Generate sitemap.xml. Makes a list of urls and date modified."""
37 | pages=[]
38 | ten_days_ago=datetime.now() - timedelta(days=10).date().isoformat()
39 | # static pages
40 | for rule in current_app.url_map.iter_rules():
41 | if "GET" in rule.methods and len(rule.arguments)==0:
42 | pages.append(
43 | [rule.rule,ten_days_ago]
44 | )
45 |
46 | # user model pages
47 | users=User.query.order_by(User.modified_time).all()
48 | for user in users:
49 | url=url_for('user.pub',name=user.name)
50 | modified_time=user.modified_time.date().isoformat()
51 | pages.append([url,modified_time])
52 |
53 | sitemap_xml = render_template('frontend/sitemap_template.xml', pages=pages)
54 | response= make_response(sitemap_xml)
55 | response.headers["Content-Type"] = "application/xml"
56 |
57 | return responseapp.route('/')
58 |
59 |
60 | """
61 |
62 |
63 | {% for page in pages %}
64 |
65 | {{page[0]|safe}}
66 | {{page[1]}}
67 |
68 | {% endfor %}
69 |
70 | """
71 |
72 |
73 | def index():
74 | return 'index'
75 |
76 |
77 | if __name__ == "__main__":
78 | app.run()
79 |
--------------------------------------------------------------------------------
/urls/generate_slug.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | urls.generate_slug
4 | ~~~~~~~~~~~~~~~~~~
5 |
6 | Generating Slugs
7 | http://flask.pocoo.org/snippets/5/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | import re
14 | from unicodedata import normalize
15 |
16 | from flask import request, Response
17 | #from unidecode import unidecode
18 |
19 | from app import app
20 |
21 |
22 | _punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
23 |
24 |
25 | def slugify(text, delim=u'-'):
26 | """Generates an ASCII-only slug."""
27 | result = []
28 | for word in _punct_re.split(text.lower()):
29 | word = word.encode('translit/long')
30 | if word:
31 | result.append(word)
32 | return unicode(delim.join(result))
33 |
34 |
35 | def slugify2(text, delim=u'-'):
36 | """Generates an slightly worse ASCII-only slug."""
37 | result = []
38 | for word in _punct_re.split(text.lower()):
39 | word = normalize('NFKD', word).encode('ascii', 'ignore')
40 | if word:
41 | result.append(word)
42 | return unicode(delim.join(result))
43 |
44 |
45 | def slugify3(text, delim=u'-'):
46 | """Generates an ASCII-only slug."""
47 | result = []
48 | for word in _punct_re.split(text.lower()):
49 | result.extend(unidecode(word).split())
50 | return unicode(delim.join(result))
51 |
52 |
53 | @app.route('/')
54 | def index():
55 | return 'index'
56 |
57 |
58 | if __name__ == "__main__":
59 | # print slugify('Hello World')
60 | # print slugify('ü')
61 | print slugify2(u'Hello World')
62 | print slugify2(u'ü')
63 | app.run()
64 |
--------------------------------------------------------------------------------
/urls/list_routes.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | urls.routes
4 | ~~~~~~~~~~~
5 |
6 | Helper to list routes (like Rail's rake routes)
7 | http://flask.pocoo.org/snippets/117/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response, url_for
15 |
16 | from app import app
17 |
18 |
19 | @app.route('/')
20 | def index():
21 | return 'index'
22 |
23 |
24 | @app.route('/test//', methods=['GET', 'POST'])
25 | def test(en):
26 | return en
27 |
28 |
29 | def list_routes():
30 | import urllib
31 | output = []
32 | for rule in app.url_map.iter_rules():
33 | options = {}
34 | for arg in rule.arguments:
35 | options[arg] = "[{0}]".format(arg)
36 |
37 | methods = ','.join(rule.methods)
38 | url = url_for(rule.endpoint, **options)
39 | # url = rule.rule
40 | line = urllib.unquote("{:50s} {:20s} {}".format(
41 | rule.endpoint, methods, url))
42 | output.append(line)
43 |
44 | for line in sorted(output):
45 | print line
46 |
47 |
48 | if __name__ == "__main__":
49 | ctx = app.test_request_context()
50 | ctx.push()
51 | list_routes()
52 |
--------------------------------------------------------------------------------
/urls/permalink.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | urls.permalink
4 | ~~~~~~~~~~~~~~
5 |
6 | Permalink function decorator
7 | http://flask.pocoo.org/snippets/6/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import url_for
15 | from werkzeug.routing import BuildError
16 |
17 | from app import app
18 |
19 |
20 | def permalink(function):
21 | def inner(*args, **kwargs):
22 | endpoint, values = function(*args, **kwargs)
23 | try:
24 | return url_for(endpoint, **values)
25 | except BuildError:
26 | return
27 | return inner
28 |
29 |
30 | @permalink
31 | def absolute_url():
32 | return 'profiles', {'username': 'fsp'}
33 |
34 |
35 | @app.route('/profiles//')
36 | def profiles(username):
37 | return username
38 |
39 |
40 | if __name__ == "__main__":
41 | ctx = app.test_request_context()
42 | ctx.push()
43 | print absolute_url()
44 |
--------------------------------------------------------------------------------
/urls/static_cache_buster.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | urls.static_cache_buster
4 | ~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | static url cache buster
7 | http://flask.pocoo.org/snippets/40/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response, url_for
15 |
16 | from app import app
17 |
18 |
19 | """
20 |
22 | """
23 |
24 |
25 | @app.context_processor
26 | def override_url_for():
27 | return dict(url_for=dated_url_for)
28 |
29 |
30 | def dated_url_for(endpoint, **values):
31 | if endpoint == 'static':
32 | filename = values.get('filename', None)
33 | if filename:
34 | file_path = os.path.join(app.root_path, endpoint, filename)
35 | values['q'] = int(os.stat(file_path).st_mtime)
36 | return url_for(endpoint, **values)
37 |
38 |
39 | @app.route('/')
40 | def index():
41 | return dated_url_for('static', filename='fsp.jpg')
42 |
43 |
44 | if __name__ == "__main__":
45 | app.run()
46 |
--------------------------------------------------------------------------------
/urls/support_semicolon.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | urls.support_semicolon
4 | ~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Supporting “;” as Delimiter in Legacy Query Strings
7 | http://flask.pocoo.org/snippets/43/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | from functools import wraps
14 |
15 | from flask import request, Response
16 |
17 | from app import app
18 |
19 |
20 | class QueryStringRedirectMiddle(object):
21 |
22 | def __init__(self, application):
23 | self.application = application
24 |
25 | def __call__(self, environ, start_response):
26 | qs = environ.get('QUERY_STRING', '')
27 | environ['QUERY_STRING'] = qs.replace(';', '&')
28 | return self.application(environ, start_response)
29 |
30 |
31 | @app.route('/')
32 | def index():
33 | print request.args
34 | return 'index'
35 |
36 |
37 | if __name__ == "__main__":
38 | app.wsgi_app = QueryStringRedirectMiddle(app.wsgi_app)
39 | app.run()
40 |
--------------------------------------------------------------------------------
/urls/url_contain_slash.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | urls.url_contain_slash
4 | ~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Handling URLs containing slash '/' character
7 | http://flask.pocoo.org/snippets/76/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response
15 |
16 | from app import app
17 |
18 |
19 | @app.route('//fsp')
20 | def index(test):
21 | return test
22 |
23 |
24 | @app.route('/product/')
25 | def product(code):
26 | return code
27 |
28 |
29 | if __name__ == "__main__":
30 | app.run()
31 |
--------------------------------------------------------------------------------
/urls/url_payload.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | urls.url_payload
4 | ~~~~~~~~~~~~~~~~
5 |
6 | URLs with Payload
7 | http://flask.pocoo.org/snippets/50/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request, Response
15 | from flask import abort, redirect, flash, url_for
16 | from itsdangerous import URLSafeSerializer, BadSignature
17 |
18 | from app import app
19 |
20 |
21 | def get_serializer(secret_key=None):
22 | if secret_key is None:
23 | secret_key = app.secret_key
24 | return URLSafeSerializer(secret_key)
25 |
26 |
27 | def get_activation_link(user):
28 | s = get_serializer()
29 | payload = s.dumps(user.id)
30 | return url_for('activate_user', payload=payload, _external=True)
31 |
32 |
33 | @app.route('/users/activate/')
34 | def activate_user(payload):
35 | s = get_serializer()
36 | try:
37 | user_id = s.loads(payload)
38 | except BadSignature:
39 | abort(404)
40 |
41 | # user = User.query.get_or_404(user_id)
42 | # user.activate()
43 | flash('User activated')
44 | return redirect(url_for('index'))
45 |
46 |
47 | @app.route('/')
48 | def index():
49 | return 'index'
50 |
51 |
52 | @app.route('/voucher/redeem/')
53 | def redeem_voucher(payload):
54 | s = get_serializer()
55 | try:
56 | user_id, voucher_id = s.loads(payload)
57 | except BadSignature:
58 | abort(404)
59 |
60 | user = User.query.get_or_404(user_id)
61 | voucher = Voucher.query.get_or_404(voucher_id)
62 | voucher.redeem_for(user)
63 | flash('Voucher redeemed')
64 | return redirect(url_for('index'))
65 |
66 | def get_redeem_link(user, voucher):
67 | s = get_serializer()
68 | payload = s.dumps([user.id, voucher.id])
69 | return url_for('redeem_voucher', payload=payload,
70 | _external=True)
71 |
72 |
73 | if __name__ == "__main__":
74 | ctx = app.test_request_context()
75 | ctx.push()
76 | class User(object):
77 | id = 10000
78 | user = User()
79 | print get_activation_link(user)
80 |
--------------------------------------------------------------------------------
/utilities/after_request_per.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.after_request_per
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Per-Request After-Request Callbacks
7 | http://flask.pocoo.org/snippets/53/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import g
15 |
16 | from app import app
17 |
18 |
19 | def after_this_request(func):
20 | if not hasattr(g, 'call_after_request'):
21 | g.call_after_request = []
22 | g.call_after_request.append(func)
23 | return func
24 |
25 |
26 | @app.after_request
27 | def per_request_callbacks(response):
28 | for func in getattr(g, 'call_after_request', ()):
29 | response = func(response)
30 | return response
31 |
32 |
33 | def invalidate_username_cache():
34 | @after_this_request
35 | def delete_username_cookie(response):
36 | response.delete_cookie('username')
37 | return response
38 |
--------------------------------------------------------------------------------
/utilities/cms_pages.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.cms_pages
4 | ~~~~~~~~~~~~~~~~~~~
5 |
6 | CMS Pages
7 | http://flask.pocoo.org/snippets/114/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import render_template_string
15 |
16 | from app import app
17 |
18 |
19 | class Page(Base):
20 | __tablename__='pages'
21 | id Column(Integer, primary_key=True)
22 | name = Column(String())
23 | page_snippets = relationship('PageSnippets', backref='pages', lazy='dynamic')
24 |
25 |
26 | class PageSnippets('base')
27 | __tablename__='page_snippets'
28 | id Column(Integer, primary_key=True)
29 | snippet = Column(String())
30 | language = Column(String())
31 |
32 |
33 | html_content = """
34 | {{page_snippets.intro}}
35 |
38 | """
39 |
40 |
41 | @app.route('/')
42 | def a_page(page_id):
43 | page = Page.query.filter_by(id=page_id).one()
44 | page_snippets = page.page_snippets
45 | return render_template_string(html_content, page_snippets=page_snippets)
46 |
--------------------------------------------------------------------------------
/utilities/content_negotiated_error.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.context_global_socketio
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Using Context Globals with Gevent-Socketio
7 | http://flask.pocoo.org/snippets/105/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from socketio import socketio_manage
15 | @app.route('/socket.io/')
16 | def run_socketio(path):
17 | real_request = request._get_current_object()
18 | socketio_manage(request.environ, {'': FlaskNamespace},
19 | request=real_request)
20 | return Response()
21 |
22 | from socketio.namespace import BaseNamespace
23 | class FlaskNamespace(BaseNamespace):
24 | def __init__(self, *args, **kwargs):
25 | request = kwargs.get('request', None)
26 | self.ctx = None
27 | if request:
28 | self.ctx = current_app.request_context(request.environ)
29 | self.ctx.push()
30 | current_app.preprocess_request()
31 | del kwargs['request']
32 | super(BaseNamespace, self).__init__(*args, **kwargs)
33 |
34 | def disconnect(self, *args, **kwargs):
35 | if self.ctx:
36 | self.ctx.pop()
37 | super(BaseNamespace, self).disconnect(*args, **kwargs)
38 |
--------------------------------------------------------------------------------
/utilities/context_global_socketio.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.cms_pages
4 | ~~~~~~~~~~~~~~~~~~~
5 |
6 | CMS Pages
7 | http://flask.pocoo.org/snippets/114/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import render_template_string
15 |
16 | from app import app
17 |
18 |
19 | class Page(Base):
20 | __tablename__='pages'
21 | id Column(Integer, primary_key=True)
22 | name = Column(String())
23 | page_snippets = relationship('PageSnippets', backref='pages', lazy='dynamic')
24 |
25 |
26 | class PageSnippets('base')
27 | __tablename__='page_snippets'
28 | id Column(Integer, primary_key=True)
29 | snippet = Column(String())
30 | language = Column(String())
31 |
32 |
33 | html_content = """
34 | {{page_snippets.intro}}
35 |
38 | """
39 |
40 |
41 | @app.route('/')
42 | def a_page(page_id):
43 | page = Page.query.filter_by(id=page_id).one()
44 | page_snippets = page.page_snippets
45 | return render_template_string(html_content, page_snippets=page_snippets)
46 |
--------------------------------------------------------------------------------
/utilities/custom_http_method.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.custom_http_method
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Custom HTTP methods
7 | http://flask.pocoo.org/snippets/1/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import render_template_string
15 |
16 | from app import app
17 |
18 |
19 | @app.before_request
20 | def before_request():
21 | method = request.form.get('_method', '').upper()
22 | if method:
23 | request.environ['REQUEST_METHOD'] = method
24 | ctx = flask._request_ctx_stack.top
25 | ctx.url_adapter.default_method = method
26 | assert request.method == method
27 |
28 |
29 | @app.route('/entries/', methods=['DELETE'])
30 | def delete_entry(id):
31 | pass
32 |
33 | """
34 |
38 | """
39 |
--------------------------------------------------------------------------------
/utilities/flask_mail.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.flask_mail
4 | ~~~~~~~~~~~~~~~~~~~~
5 |
6 | Flask-Mail with google apps
7 | http://flask.pocoo.org/snippets/85/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import Flask
15 | from flaskext.mail import Mail, Message
16 |
17 | app =Flask(__name__)
18 | mail=Mail(app)
19 |
20 | app.config.update(
21 | DEBUG=True,
22 | #EMAIL SETTINGS
23 | MAIL_SERVER='smtp.gmail.com',
24 | MAIL_PORT=465,
25 | MAIL_USE_SSL=True,
26 | MAIL_USERNAME = 'you@google.com',
27 | MAIL_PASSWORD = 'GooglePasswordHere'
28 | )
29 |
30 | mail=Mail(app)
31 |
32 | @app.route("/")
33 | def index():
34 | msg = Message(
35 | 'Hello',
36 | sender='you@dgoogle.com',
37 | recipients=
38 | ['recipient@recipient_domain.com'])
39 | msg.body = "This is the email body"
40 | mail.send(msg)
41 | return "Sent"
42 |
43 | if __name__ == "__main__":
44 | app.run()
45 |
--------------------------------------------------------------------------------
/utilities/flask_testcase.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.flask_testcase
4 | ~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Flask TestCase
7 | http://flask.pocoo.org/snippets/26/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | import unittest
14 |
15 | from flask import render_template_string
16 |
17 | from app import app
18 |
19 |
20 | class TestCase(unittest.TestCase):
21 |
22 | def create_app(self):
23 | """
24 | Create your Flask app here, with any
25 | configuration you need
26 | """
27 | raise NotImplementedError
28 |
29 | def __call__(self, result=None):
30 | """
31 | Does the required setup, doing it here
32 | means you don't have to call super.setUp
33 | in subclasses.
34 | """
35 | self._pre_setup()
36 | super(TestCase, self).__call__(result)
37 | self._post_tearDown()
38 |
39 | def _pre_setup(self):
40 | self.app = self.create_app()
41 | self.client = self.app.test_client()
42 |
43 | # now you can use flask thread locals
44 |
45 | self._ctx = self.app.test_request_context()
46 | self._ctx.push()
47 |
48 | def _post_tearDown(self):
49 | self._ctx.pop()
50 |
51 | def assert404(self, response):
52 | """
53 | Checks if a HTTP 404 returned
54 | e.g.
55 | resp = self.client.get("/")
56 | self.assert404(resp)
57 | """
58 | self.assertTrue(response.status_code == 404)
59 |
--------------------------------------------------------------------------------
/utilities/import_css_string.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.import_css_string
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Include / Import css file as string
7 | http://flask.pocoo.org/snippets/77/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import render_template_string
15 |
16 | from app import app
17 |
18 |
19 | def get_resource_as_string(name, charset='utf-8'):
20 | with app.open_resource(name) as f:
21 | return f.read().decode(charset)
22 |
23 | app.jinja_env.globals['get_resource_as_string'] = get_resource_as_string
24 |
25 |
26 | """
27 |
28 | """
29 |
--------------------------------------------------------------------------------
/utilities/interactive_shell.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.interactive_shell
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Preconfigured interactive shell
7 | http://flask.pocoo.org/snippets/23/
8 | """
9 |
10 | import os
11 | import readline
12 | from pprint import pprint
13 |
14 | from flask import *
15 |
16 | from myapp import *
17 | from utils import *
18 | from db import *
19 | from models import *
20 |
21 |
22 | os.environ['PYTHONINSPECT'] = 'True'
23 |
--------------------------------------------------------------------------------
/utilities/json_encoder.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.json_encoder
4 | ~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Custom Flask JSONEncoder
7 | http://flask.pocoo.org/snippets/119/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | from datetime import datetime
14 | import calendar
15 |
16 | from flask import jsonify
17 | from flask.json import JSONEncoder
18 |
19 | from app import app
20 |
21 |
22 | class CustomJSONEncoder(JSONEncoder):
23 |
24 | def default(self, obj):
25 | try:
26 | if isinstance(obj, datetime):
27 | if obj.utcoffset() is not None:
28 | obj = obj - obj.utcoffset()
29 | millis = int(
30 | calendar.timegm(obj.timetuple()) * 1000 +
31 | obj.microsecond / 1000
32 | )
33 | return millis
34 | iterable = iter(obj)
35 | except TypeError:
36 | pass
37 | else:
38 | return list(iterable)
39 | return JSONEncoder.default(self, obj)
40 |
41 |
42 | app.json_encoder = CustomJSONEncoder
43 |
44 |
45 | @app.route('/custom')
46 | def custom_jsonencoder():
47 | now = datetime.now()
48 | return jsonify({'now': now})
49 |
50 |
51 | if __name__ == '__main__':
52 | app.run()
53 |
--------------------------------------------------------------------------------
/utilities/local_proxy.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.local_proxy
4 | ~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Creating your own local proxies
7 | http://flask.pocoo.org/snippets/13/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from werkzeug.local import LocalProxy
15 |
16 | from app import app
17 |
18 |
19 | whatever = LocalProxy(lambda: g.whatever)
20 | method = LocalProxy(lambda: request.method)
21 |
--------------------------------------------------------------------------------
/utilities/nice_errors.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.nice_errors
4 | ~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Nicer Errors with Descriptions from Werkzeug
7 | http://flask.pocoo.org/snippets/15/
8 | """
9 |
10 | from flask import Markup, render_template
11 | from werkzeug.exceptions import default_exceptions
12 |
13 | def show_errormessage(error):
14 | desc = error.get_description(flask.request.environ)
15 | return render_template('error.html',
16 | code=error.code,
17 | name=error.name,
18 | description=Markup(desc)
19 | ), error.code
20 |
21 | for _exc in default_exceptions:
22 | app.error_handlers[_exc] = show_errormessage
23 | del _exc
24 |
25 |
26 | """
27 | {% extends "base.html" %}
28 | {% block title %}Error {{ code }}: {{ name }}{% endblock %}
29 | {% block body %}
30 | {{ description}}
31 | {% endblock %}
32 | """
33 |
--------------------------------------------------------------------------------
/utilities/override_httpmethod.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.override_httpmethod
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Overriding HTTP Methods for old browsers
7 | http://flask.pocoo.org/snippets/38/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from werkzeug import url_decode
15 |
16 | class MethodRewriteMiddleware(object):
17 |
18 | def __init__(self, app):
19 | self.app = app
20 |
21 | def __call__(self, environ, start_response):
22 | if 'METHOD_OVERRIDE' in environ.get('QUERY_STRING', ''):
23 | args = url_decode(environ['QUERY_STRING'])
24 | method = args.get('__METHOD_OVERRIDE__')
25 | if method:
26 | method = method.encode('ascii', 'replace')
27 | environ['REQUEST_METHOD'] = method
28 | return self.app(environ, start_response)
29 |
30 |
31 | """
32 |
35 | """
36 |
--------------------------------------------------------------------------------
/utilities/reloading.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.reloading
4 | ~~~~~~~~~~~~~~~~~~~
5 |
6 | Reloading with other WSGI servers
7 | http://flask.pocoo.org/snippets/34/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | import gevent.wsgi
15 | import werkzeug.serving
16 |
17 | from app import app
18 |
19 |
20 | @werkzeug.serving.run_with_reloader
21 | def runServer():
22 | ws = gevent.wsgi.WSGIServer(('', 5000), app)
23 | ws.serve_forever()
24 |
25 |
26 | if __name__ == "__main__":
27 | runServer()
28 |
--------------------------------------------------------------------------------
/utilities/rq.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.rq
4 | ~~~~~~~~~~~~
5 |
6 | Basic Message Queue with Redis
7 | http://flask.pocoo.org/snippets/73/
8 | """
9 |
10 | import os
11 | import sys
12 | from uuid import uuid4
13 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
14 | from pickle import loads, dumps
15 |
16 | from redis import Redis
17 | from flask import current_app
18 | from flask import session, abort, jsonify
19 |
20 | from app import app
21 |
22 |
23 | # Connecting to Redis
24 | redis = Redis()
25 |
26 |
27 | # The Configuration
28 | app.config['REDIS_QUEUE_KEY'] = 'my_queue'
29 |
30 |
31 | class DelayedResult(object):
32 | def __init__(self, key):
33 | self.key = key
34 | self._rv = None
35 |
36 | @property
37 | def return_value(self):
38 | if self._rv is None:
39 | rv = redis.get(self.key)
40 | if rv is not None:
41 | self._rv = loads(rv)
42 | return self._rv
43 |
44 |
45 | def queuefunc(f):
46 | def delay(*args, **kwargs):
47 | qkey = current_app.config['REDIS_QUEUE_KEY']
48 | key = '%s:result:%s' % (qkey, str(uuid4()))
49 | s = dumps((f, key, args, kwargs))
50 | redis.rpush(current_app.config['REDIS_QUEUE_KEY'], s)
51 | return DelayedResult(key)
52 | f.delay = delay
53 | return f
54 |
55 |
56 | def queue_daemon(app, rv_ttl=500):
57 | while 1:
58 | msg = redis.blpop(app.config['REDIS_QUEUE_KEY'])
59 | func, key, args, kwargs = loads(msg[1])
60 | try:
61 | rv = func(*args, **kwargs)
62 | except Exception, e:
63 | rv = e
64 | if rv is not None:
65 | redis.set(key, dumps(rv))
66 | redis.expire(key, rv_ttl)
67 |
68 |
69 | @queuefunc
70 | def add(a, b):
71 | return a + b
72 |
73 |
74 | @app.route('/add')
75 | def add_numbers():
76 | a = request.args.get('a', type=int)
77 | b = request.args.get('b', type=int)
78 | if a is None or b is None:
79 | abort(400)
80 | rv = add.delay(a, b)
81 | session['add_result_key'] = rv.key
82 | return 'Waiting for result...'
83 |
84 |
85 | @app.route('/add-result')
86 | def add_numbers_result():
87 | key = session.get('add_result_key')
88 | if key is None:
89 | return jsonify(ready=False)
90 | rv = DelayedResult(key)
91 | if rv.return_value is None:
92 | return jsonify(ready=False)
93 | redis.delete(key)
94 | del session['add_result_key']
95 | return jsonify(ready=True, result=rv.return_value)
96 |
97 |
98 | if __name__ == "__main__":
99 | ctx = app.test_request_context()
100 | ctx.push()
101 | rv = add.delay(1, 2)
102 | import threading
103 | daemon = threading.Thread(target=queue_daemon, args=(app,))
104 | daemon.setDaemon(True)
105 | daemon.start()
106 | while True:
107 | rt = rv.return_value
108 | if rt is None:
109 | continue
110 | else:
111 | print rt
112 | print rv.key
113 | break
114 |
--------------------------------------------------------------------------------
/utilities/serve_transcompiling.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.serve_transcompiling
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Serve CoffeeScript, SCSS, or other transcompiling file via Python
7 | http://flask.pocoo.org/snippets/90/
8 | """
9 |
10 | from subprocess import Popen, PIPE
11 | import shlex
12 |
13 | class NonZeroExitError(Exception):
14 | def __init__(self, command, returncode, output, error):
15 | self.command = command
16 | self.returncode = returncode
17 | self.output = output
18 | self.error = error
19 | def __str__(self):
20 | return '''\
21 | %s returned non-zero exit status %d with output
22 | %s
23 | and error
24 | %s''' % (self.command, self.returncode,
25 | self.output or "[NO OUTOUT]",
26 | self.error or "[NO ERROR]")
27 |
28 | def command_line_renderer_factory(command):
29 | '''command should be a command reads input from stdin
30 | and prints to stdout'''
31 |
32 | args = shlex.split(command)
33 |
34 | def renderer(script):
35 | '''Accepts a file object or path and return the
36 | rendered string'''
37 |
38 | if isinstance(script, file):
39 | pass
40 | elif isinstance(script, str):
41 | script = open(script)
42 | else:
43 | raise TypeError('script must be a file object of '
44 | 'or a string to the file')
45 | process = Popen(args, stdin=script,
46 | stdout=PIPE, stderr=PIPE)
47 |
48 | returncode = process.wait()
49 | stdoutdata, stderrdata = process.communicate()
50 |
51 | if returncode != 0:
52 | raise NonZeroExitError(command, returncode,
53 | stdoutdata, stderrdata)
54 |
55 | return stdoutdata
56 |
57 | return renderer
58 |
59 |
60 | """
61 | #!/usr/bin/env node
62 |
63 | var less = require('less');
64 |
65 | process.stdin.resume();
66 | process.stdin.setEncoding('utf8');
67 |
68 | process.stdin.on('data', function (less_css) {
69 | less.render(less_css, function(e, css){
70 | console.log(css)
71 | });
72 | });
73 | """
74 |
--------------------------------------------------------------------------------
/utilities/set_cookies.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.set_cookies
4 | ~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Flask Set Cookies by Response
7 | http://flask.pocoo.org/snippets/30/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import redirect, current_app
15 |
16 | from app import app
17 |
18 |
19 | @app.route('/set_cookie')
20 | def cookie_insertion():
21 | redirect_to_index = redirect('/index')
22 | response = current_app.make_response(redirect_to_index)
23 | response.set_cookie('cookie_name',value='values')
24 | return response
25 |
--------------------------------------------------------------------------------
/utilities/share_server.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.share_server
4 | ~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Share your Local Server with a Friend
7 | http://flask.pocoo.org/snippets/89/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import render_template_string
15 |
16 | from app import app
17 |
18 |
19 | """
20 | $ sudo gem install localtunnel
21 | $ localtunnel 5000
22 | $ Port 5000 is now publicly accessible from http://54xy.localtunnel.com ...
23 | """
24 |
--------------------------------------------------------------------------------
/utilities/shutdown_server.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.shutdown_server
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Shutdown The Simple Server
7 | http://flask.pocoo.org/snippets/67/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import request
15 |
16 | from app import app
17 |
18 |
19 | def shutdown_server():
20 | func = request.environ.get('werkzeug.server.shutdown')
21 | if func is None:
22 | raise RuntimeError('Not running with the Werkzeug Server')
23 | func()
24 |
25 |
26 | @app.route('/shutdown', methods=['GET', 'POST'])
27 | def shutdown():
28 | shutdown_server()
29 | return 'Server shutting down...'
30 |
31 |
32 | if __name__ == "__main__":
33 | app.run()
34 |
--------------------------------------------------------------------------------
/utilities/sqlite_q.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.sqlite_q
4 | ~~~~~~~~~~~~~~~~~~
5 |
6 | Job queue implemented using SQLite
7 | http://flask.pocoo.org/snippets/88/
8 | """
9 |
10 | import os, sqlite3
11 | from cPickle import loads, dumps
12 | from time import sleep
13 | try:
14 | from thread import get_ident
15 | except ImportError:
16 | from dummy_thread import get_ident
17 |
18 |
19 | class SqliteQueue(object):
20 |
21 | _create = (
22 | 'CREATE TABLE IF NOT EXISTS queue '
23 | '('
24 | ' id INTEGER PRIMARY KEY AUTOINCREMENT,'
25 | ' item BLOB'
26 | ')'
27 | )
28 | _count = 'SELECT COUNT(*) FROM queue'
29 | _iterate = 'SELECT id, item FROM queue'
30 | _append = 'INSERT INTO queue (item) VALUES (?)'
31 | _write_lock = 'BEGIN IMMEDIATE'
32 | _popleft_get = (
33 | 'SELECT id, item FROM queue '
34 | 'ORDER BY id LIMIT 1'
35 | )
36 | _popleft_del = 'DELETE FROM queue WHERE id = ?'
37 | _peek = (
38 | 'SELECT item FROM queue '
39 | 'ORDER BY id LIMIT 1'
40 | )
41 |
42 | def __init__(self, path):
43 | self.path = os.path.abspath(path)
44 | self._connection_cache = {}
45 | with self._get_conn() as conn:
46 | conn.execute(self._create)
47 |
48 | def __len__(self):
49 | with self._get_conn() as conn:
50 | l = conn.execute(self._count).next()[0]
51 | return l
52 |
53 | def __iter__(self):
54 | with self._get_conn() as conn:
55 | for id, obj_buffer in conn.execute(self._iterate):
56 | yield loads(str(obj_buffer))
57 |
58 | def _get_conn(self):
59 | id = get_ident()
60 | if id not in self._connection_cache:
61 | self._connection_cache[id] = sqlite3.Connection(self.path,
62 | timeout=60)
63 | return self._connection_cache[id]
64 |
65 | def append(self, obj):
66 | obj_buffer = buffer(dumps(obj, 2))
67 | with self._get_conn() as conn:
68 | conn.execute(self._append, (obj_buffer,))
69 |
70 | def popleft(self, sleep_wait=True):
71 | keep_pooling = True
72 | wait = 0.1
73 | max_wait = 2
74 | tries = 0
75 | with self._get_conn() as conn:
76 | id = None
77 | while keep_pooling:
78 | conn.execute(self._write_lock)
79 | cursor = conn.execute(self._popleft_get)
80 | try:
81 | id, obj_buffer = cursor.next()
82 | keep_pooling = False
83 | except StopIteration:
84 | conn.commit() # unlock the database
85 | if not sleep_wait:
86 | keep_pooling = False
87 | continue
88 | tries += 1
89 | sleep(wait)
90 | wait = min(max_wait, tries/10 + wait)
91 | if id:
92 | conn.execute(self._popleft_del, (id,))
93 | return loads(str(obj_buffer))
94 | return None
95 |
96 | def peek(self):
97 | with self._get_conn() as conn:
98 | cursor = conn.execute(self._peek)
99 | try:
100 | return loads(str(cursor.next()[0]))
101 | except StopIteration:
102 | return None
103 |
--------------------------------------------------------------------------------
/utilities/stream_proxy.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.stream_proxy
4 | ~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Stream Proxy with Requests
7 | http://flask.pocoo.org/snippets/118/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import Response, stream_with_context
15 | import requests
16 |
17 | from app import app
18 |
19 |
20 | @app.route('/')
21 | def home(url):
22 | req = requests.get(url, stream=True)
23 | return Response(stream_with_context(req.iter_content()), content_type = req.headers['content-type'])
24 |
25 |
26 | if __name__ == '__main__':
27 | app.run()
28 |
--------------------------------------------------------------------------------
/utilities/trigger_debuggr.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.trigger_debugger
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Triggering the debugger on purpose
7 | http://flask.pocoo.org/snippets/21/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import render_template_string
15 |
16 | from app import app
17 |
18 |
19 | @app.route('/')
20 | def index():
21 | do_something_wrong()
22 | raise
23 | return 'Ohnoes'
24 |
25 |
26 | """
27 | assert app.debug == False
28 | """
29 |
--------------------------------------------------------------------------------
/utilities/turbomail.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.turbomail
4 | ~~~~~~~~~~~~~~~~~~~
5 |
6 | Using TurboMail with Flask
7 | http://flask.pocoo.org/snippets/16/
8 | """
9 |
10 | import atexit
11 |
12 | from turbomail.control import interface
13 | from turbomail.message import Message
14 |
15 | from flask import Flask
16 |
17 | # pass in dict of config options
18 |
19 | interface.start({'mail.on' : True})
20 |
21 | # ensures interface cleanly shutdown when process exits
22 |
23 | atexit.register(interface.stop, force=True)
24 |
25 | app = Flask(__name__)
26 |
27 | @app.route("/")
28 | def index():
29 | # send an email
30 | msg = Message("from@example.com",
31 | "to@example.com",
32 | "a subject")
33 | msg.plain = "body of message"
34 | msg.send()
35 |
--------------------------------------------------------------------------------
/utilities/upload_stringio.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.upload_stringio
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Upload a StringIO object with send_file
7 | http://flask.pocoo.org/snippets/32/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 | import StringIO
14 |
15 | from flask import send_fileg
16 |
17 | from app import app
18 |
19 |
20 | @app.route('/')
21 | def index():
22 | strIO = StringIO.StringIO()
23 | strIO.write('Hello from Dan Jacob and Stephane Wirtel !')
24 | strIO.seek(0)
25 | return send_file(strIO,
26 | attachment_filename="testing.txt",
27 | as_attachment=True)
28 |
29 |
30 | if __name__ == "__main__":
31 | app.run()
32 |
--------------------------------------------------------------------------------
/utilities/wtform_flash_error.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | utilities.wtform_flash_error
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Flashing errors from WTForms forms
7 | http://flask.pocoo.org/snippets/12/
8 | """
9 |
10 | import os
11 | import sys
12 | sys.path.insert(0, os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
13 |
14 | from flask import render_template_string
15 |
16 | from app import app
17 |
18 |
19 | def flash_errors(form):
20 | for field, errors in form.errors.items():
21 | for error in errors:
22 | flash(u"Error in the %s field - %s" % (
23 | getattr(form, field).label.text,
24 | error
25 | ))
26 |
--------------------------------------------------------------------------------