Merge branch 'master' of github.com:mitsuhiko/flask
This commit is contained in:
commit
2e816f554a
21 changed files with 166 additions and 56 deletions
15
.travis.yml
Normal file
15
.travis.yml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
language: python
|
||||
|
||||
python:
|
||||
- 2.5
|
||||
- 2.6
|
||||
- 2.7
|
||||
- pypy
|
||||
|
||||
before_install: pip install simplejson
|
||||
|
||||
script: python setup.py test
|
||||
|
||||
branches:
|
||||
except:
|
||||
- website
|
||||
|
|
@ -25,8 +25,9 @@ The :ref:`api` docs are full of available overrides, hook points, and
|
|||
response objects. Dig deeper on the APIs you use, and look for the
|
||||
customizations which are available out of the box in a Flask release. Look for
|
||||
ways in which your project can be refactored into a collection of utilities and
|
||||
Flask extensions. Explore the many extensions in the community, and look for
|
||||
patterns to build your own extensions if you do not find the tools you need.
|
||||
Flask extensions. Explore the many `extensions
|
||||
<http://flask.pocoo.org/extensions/>` in the community, and look for patterns to
|
||||
build your own extensions if you do not find the tools you need.
|
||||
|
||||
Subclass.
|
||||
---------
|
||||
|
|
|
|||
|
|
@ -35,12 +35,23 @@ Usually there are two ways to configure the server. Either just copy the
|
|||
`.cgi` into a `cgi-bin` (and use `mod_rewrite` or something similar to
|
||||
rewrite the URL) or let the server point to the file directly.
|
||||
|
||||
In Apache for example you can put a like like this into the config:
|
||||
In Apache for example you can put something like this into the config:
|
||||
|
||||
.. sourcecode:: apache
|
||||
|
||||
ScriptAlias /app /path/to/the/application.cgi
|
||||
|
||||
On shared webhosting, though, you might not have access to your Apache config.
|
||||
In this case, a file called `.htaccess`, sitting in the public directory you want
|
||||
your app to be available, works too but the `ScriptAlias` directive won't
|
||||
work in that case:
|
||||
|
||||
.. sourcecode:: apache
|
||||
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-f # Don't interfere with static files
|
||||
RewriteRule ^(.*)$ /path/to/the/application.cgi/$1 [L]
|
||||
|
||||
For more information consult the documentation of your webserver.
|
||||
|
||||
.. _App Engine: http://code.google.com/appengine/
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ Set yourapplication.fcgi::
|
|||
|
||||
def __call__(self, environ, start_response):
|
||||
environ['SCRIPT_NAME'] = ''
|
||||
return self.app(environ, start_response)
|
||||
return self.app(environ, start_response)
|
||||
|
||||
app = ScriptNameStripper(app)
|
||||
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ registered on PyPI. Also the development checkout link should work so
|
|||
that people can easily install the development version into their
|
||||
virtualenv without having to download the library by hand.
|
||||
|
||||
Flask extensions must be licensed as BSD or MIT or a more liberal license
|
||||
to be enlisted on the Flask Extension Registry. Keep in mind that the
|
||||
Flask Extension Registry is a moderated place and libraries will be
|
||||
reviewed upfront if they behave as required.
|
||||
Flask extensions must be licensed under a BSD, MIT or more liberal license
|
||||
to be able to be enlisted in the Flask Extension Registry. Keep in mind
|
||||
that the Flask Extension Registry is a moderated place and libraries will
|
||||
be reviewed upfront if they behave as required.
|
||||
|
||||
"Hello Flaskext!"
|
||||
-----------------
|
||||
|
|
|
|||
|
|
@ -122,9 +122,6 @@ collection first, this is somewhat the same as a table in the SQL world.
|
|||
>>> user = {'name': u'admin', 'email': u'admin@localhost'}
|
||||
>>> collection.insert(user)
|
||||
|
||||
print list(collection.find())
|
||||
print collection.find_one({'name': u'admin'})
|
||||
|
||||
MongoKit will automatically commit for us.
|
||||
|
||||
To query your database, you use the collection directly:
|
||||
|
|
|
|||
|
|
@ -514,8 +514,9 @@ attributes mentioned above::
|
|||
return log_the_user_in(request.form['username'])
|
||||
else:
|
||||
error = 'Invalid username/password'
|
||||
# this is executed if the request method was GET or the
|
||||
# credentials were invalid
|
||||
# the code below this is executed if the request method
|
||||
# was GET or the credentials were invalid
|
||||
return render_template('login.html', error=error)
|
||||
|
||||
What happens if the key does not exist in the `form` attribute? In that
|
||||
case a special :exc:`KeyError` is raised. You can catch it like a
|
||||
|
|
|
|||
11
examples/blueprintexample/blueprintexample.py
Normal file
11
examples/blueprintexample/blueprintexample.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
from flask import Flask
|
||||
from simple_page.simple_page import simple_page
|
||||
|
||||
app = Flask(__name__)
|
||||
app.register_blueprint(simple_page)
|
||||
# Blueprint can be registered many times
|
||||
app.register_blueprint(simple_page, url_prefix='/pages')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True)
|
||||
36
examples/blueprintexample/blueprintexample_test.py
Normal file
36
examples/blueprintexample/blueprintexample_test.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Blueprint Example Tests
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Tests the Blueprint example app
|
||||
"""
|
||||
import blueprintexample
|
||||
import unittest
|
||||
|
||||
|
||||
class BlueprintExampleTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.app = blueprintexample.app.test_client()
|
||||
|
||||
def test_urls(self):
|
||||
r = self.app.get('/')
|
||||
self.assertEquals(r.status_code, 200)
|
||||
|
||||
r = self.app.get('/hello')
|
||||
self.assertEquals(r.status_code, 200)
|
||||
|
||||
r = self.app.get('/world')
|
||||
self.assertEquals(r.status_code, 200)
|
||||
|
||||
#second blueprint instance
|
||||
r = self.app.get('/pages/hello')
|
||||
self.assertEquals(r.status_code, 200)
|
||||
|
||||
r = self.app.get('/pages/world')
|
||||
self.assertEquals(r.status_code, 200)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
0
examples/blueprintexample/simple_page/__init__.py
Normal file
0
examples/blueprintexample/simple_page/__init__.py
Normal file
13
examples/blueprintexample/simple_page/simple_page.py
Normal file
13
examples/blueprintexample/simple_page/simple_page.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
from flask import Blueprint, render_template, abort
|
||||
from jinja2 import TemplateNotFound
|
||||
|
||||
simple_page = Blueprint('simple_page', __name__,
|
||||
template_folder='templates')
|
||||
|
||||
@simple_page.route('/', defaults={'page': 'index'})
|
||||
@simple_page.route('/<page>')
|
||||
def show(page):
|
||||
try:
|
||||
return render_template('pages/%s.html' % page)
|
||||
except TemplateNotFound:
|
||||
abort(404)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{% extends "pages/layout.html" %}
|
||||
|
||||
{% block body %}
|
||||
Hello
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{% extends "pages/layout.html" %}
|
||||
|
||||
{% block body %}
|
||||
Blueprint example page
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<!doctype html>
|
||||
<title>Simple Page Blueprint</title>
|
||||
<div class=page>
|
||||
<h1>This is blueprint example</h1>
|
||||
<p>
|
||||
A simple page blueprint is registered under / and /pages<br/>
|
||||
you can access it using this urls:
|
||||
<ul>
|
||||
<li><a href="{{ url_for('simple_page.show', page='hello') }}">/hello</a></li>
|
||||
<li><a href="{{ url_for('simple_page.show', page='world') }}">/world</a></li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
Also you can register the same blueprint under another path
|
||||
<ul>
|
||||
<li><a href="/pages/hello">/pages/hello</a></li>
|
||||
<li><a href="/pages/world">/pages/world</a></li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
{% block body %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{% extends "pages/layout.html" %}
|
||||
|
||||
{% block body %}
|
||||
World
|
||||
{% endblock %}
|
||||
|
|
@ -1490,7 +1490,7 @@ class Flask(_PackageBoundObject):
|
|||
"""
|
||||
funcs = self.url_default_functions.get(None, ())
|
||||
if '.' in endpoint:
|
||||
bp = endpoint.split('.', 1)[0]
|
||||
bp = endpoint.rsplit('.', 1)[0]
|
||||
funcs = chain(funcs, self.url_default_functions.get(bp, ()))
|
||||
for func in funcs:
|
||||
func(endpoint, values)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ def after_this_request(f):
|
|||
@app.route('/')
|
||||
def index():
|
||||
@after_this_request
|
||||
def add_header():
|
||||
def add_header(response):
|
||||
response.headers['X-Foo'] = 'Parachute'
|
||||
return response
|
||||
return 'Hello World!'
|
||||
|
|
|
|||
|
|
@ -118,31 +118,9 @@ def jsonify(*args, **kwargs):
|
|||
information about this, have a look at :ref:`json-security`.
|
||||
|
||||
.. versionadded:: 0.2
|
||||
|
||||
.. versionadded:: 0.9
|
||||
If the ``padded`` argument is true, the JSON object will be padded
|
||||
for JSONP calls and the response mimetype will be changed to
|
||||
``application/javascript``. By default, the request arguments ``callback``
|
||||
and ``jsonp`` will be used as the name for the callback function.
|
||||
This will work with jQuery and most other JavaScript libraries
|
||||
by default.
|
||||
|
||||
If the ``padded`` argument is a string, jsonify will look for
|
||||
the request argument with the same name and use that value as the
|
||||
callback-function name.
|
||||
"""
|
||||
if __debug__:
|
||||
_assert_have_json()
|
||||
if 'padded' in kwargs:
|
||||
if isinstance(kwargs['padded'], str):
|
||||
callback = request.args.get(kwargs['padded']) or 'jsonp'
|
||||
else:
|
||||
callback = request.args.get('callback') or \
|
||||
request.args.get('jsonp') or 'jsonp'
|
||||
del kwargs['padded']
|
||||
json_str = json.dumps(dict(*args, **kwargs), indent=None)
|
||||
content = str(callback) + "(" + json_str + ")"
|
||||
return current_app.response_class(content, mimetype='application/javascript')
|
||||
return current_app.response_class(json.dumps(dict(*args, **kwargs),
|
||||
indent=None if request.is_xhr else 2), mimetype='application/json')
|
||||
|
||||
|
|
@ -529,7 +507,7 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
|
|||
rv.cache_control.public = True
|
||||
if cache_timeout is None:
|
||||
cache_timeout = current_app.get_send_file_max_age(filename)
|
||||
if cache_timeout:
|
||||
if cache_timeout is not None:
|
||||
rv.cache_control.max_age = cache_timeout
|
||||
rv.expires = int(time() + cache_timeout)
|
||||
|
||||
|
|
|
|||
|
|
@ -953,6 +953,29 @@ class BasicFunctionalityTestCase(FlaskTestCase):
|
|||
self.assert_equal(c.get('/de/').data, '/de/about')
|
||||
self.assert_equal(c.get('/de/about').data, '/foo')
|
||||
self.assert_equal(c.get('/foo').data, '/en/about')
|
||||
|
||||
def test_inject_blueprint_url_defaults(self):
|
||||
app = flask.Flask(__name__)
|
||||
bp = flask.Blueprint('foo.bar.baz', __name__,
|
||||
template_folder='template')
|
||||
|
||||
@bp.url_defaults
|
||||
def bp_defaults(endpoint, values):
|
||||
values['page'] = 'login'
|
||||
@bp.route('/<page>')
|
||||
def view(page): pass
|
||||
|
||||
app.register_blueprint(bp)
|
||||
|
||||
values = dict()
|
||||
app.inject_url_defaults('foo.bar.baz.view', values)
|
||||
expected = dict(page='login')
|
||||
self.assert_equal(values, expected)
|
||||
|
||||
with app.test_request_context('/somepage'):
|
||||
url = flask.url_for('foo.bar.baz.view')
|
||||
expected = '/login'
|
||||
self.assert_equal(url, expected)
|
||||
|
||||
def test_debug_mode_complains_after_first_request(self):
|
||||
app = flask.Flask(__name__)
|
||||
|
|
|
|||
|
|
@ -73,28 +73,11 @@ class JSONTestCase(FlaskTestCase):
|
|||
@app.route('/dict')
|
||||
def return_dict():
|
||||
return flask.jsonify(d)
|
||||
@app.route("/unpadded")
|
||||
def return_padded_false():
|
||||
return flask.jsonify(d, padded=False)
|
||||
@app.route("/padded")
|
||||
def return_padded_true():
|
||||
return flask.jsonify(d, padded=True)
|
||||
@app.route("/padded_custom")
|
||||
def return_padded_json_custom_callback():
|
||||
return flask.jsonify(d, padded='my_func_name')
|
||||
c = app.test_client()
|
||||
for url in '/kw', '/dict', '/unpadded':
|
||||
for url in '/kw', '/dict':
|
||||
rv = c.get(url)
|
||||
self.assert_equal(rv.mimetype, 'application/json')
|
||||
self.assert_equal(flask.json.loads(rv.data), d)
|
||||
for get_arg in 'callback=funcName', 'jsonp=funcName':
|
||||
rv = c.get('/padded?' + get_arg)
|
||||
self.assert_( rv.data.startswith("funcName(") )
|
||||
self.assert_( rv.data.endswith(")") )
|
||||
rv_json = rv.data.split('(')[1].split(')')[0]
|
||||
self.assert_equal(flask.json.loads(rv_json), d)
|
||||
rv = c.get('/padded_custom?my_func_name=funcName')
|
||||
self.assert_( rv.data.startswith("funcName(") )
|
||||
|
||||
def test_json_attr(self):
|
||||
app = flask.Flask(__name__)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
Usage::
|
||||
|
||||
import flaskext_compat
|
||||
flaskext_compat.activate()
|
||||
from flask.ext import foo
|
||||
|
||||
:copyright: (c) 2011 by Armin Ronacher.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue