forked from orbit-oss/flask
Ported examples over to new config. documented upgrading
This commit is contained in:
parent
02b916d509
commit
dfecc86dd3
17 changed files with 122 additions and 39 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit f87d00eee80e4a555e94ed124a94ffea483dc329
|
||||
Subproject commit 0d8f3d85558168647632c768bdea7d58cf6f8e42
|
||||
|
|
@ -27,7 +27,6 @@ endpoints.
|
|||
Here are some suggestions for how Flask can be modified to better
|
||||
accommodate large-scale applications:
|
||||
|
||||
- implement dotted names for URL endpoints
|
||||
- get rid of the decorator function registering which causes a lot
|
||||
of troubles for applications that have circular dependencies. It
|
||||
also requires that the whole application is imported when the system
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.. _config:
|
||||
|
||||
Configuration Handling
|
||||
======================
|
||||
|
||||
|
|
@ -47,6 +49,8 @@ Builtin Configuration Values
|
|||
|
||||
The following configuration values are used internally by Flask:
|
||||
|
||||
.. tabularcolumns:: |p{6.5cm}|p{8.5cm}|
|
||||
|
||||
=============================== =========================================
|
||||
``DEBUG`` enable/disable debug mode
|
||||
``SECRET_KEY`` the secret key
|
||||
|
|
|
|||
|
|
@ -41,4 +41,5 @@ Design notes, legal information and changelog are here for the interested.
|
|||
|
||||
design
|
||||
license
|
||||
upgrading
|
||||
changelog
|
||||
|
|
|
|||
|
|
@ -84,11 +84,6 @@ widespread usage. Recent versions of Flask scale nicely within reasonable
|
|||
bounds and if you grow larger, you won't have any troubles adjusting Flask
|
||||
for your new application size.
|
||||
|
||||
Flask serves two purposes: it's an example of how to create a minimal and
|
||||
opinionated framework on top of Werkzeug to show how this can be done, and
|
||||
to provide people with a simple tool to prototype larger applications or
|
||||
to implement small and medium sized applications.
|
||||
|
||||
If you suddenly discover that your application grows larger than
|
||||
originally intended, head over to the :ref:`becomingbig` section to see
|
||||
some possible solutions for larger applications.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.. _app-factories:
|
||||
|
||||
Application Factories
|
||||
=====================
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ inside a `script` block here where different rules apply.
|
|||
will not be parsed. Everything until ``</script>`` is handled as script.
|
||||
This also means that there must never be any ``</`` between the script
|
||||
tags. ``|tojson`` is kindly enough to do the right thing here and
|
||||
escape slashes for you (``{{ "</script>"|tojson|safe }`` is rendered as
|
||||
escape slashes for you (``{{ "</script>"|tojson|safe }}`` is rendered as
|
||||
``"<\/script>"``).
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ this::
|
|||
class FlaskrTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.db_fd, flaskr.DATABASE = tempfile.mkstemp()
|
||||
self.db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp()
|
||||
self.app = flaskr.app.test_client()
|
||||
flaskr.init_db()
|
||||
|
||||
|
|
@ -151,13 +151,13 @@ Now we can easily test if logging in and out works and that it fails with
|
|||
invalid credentials. Add this new test to the class::
|
||||
|
||||
def test_login_logout(self):
|
||||
rv = self.login(flaskr.USERNAME, flaskr.PASSWORD)
|
||||
rv = self.login('admin', 'default')
|
||||
assert 'You were logged in' in rv.data
|
||||
rv = self.logout()
|
||||
assert 'You were logged out' in rv.data
|
||||
rv = self.login(flaskr.USERNAME + 'x', flaskr.PASSWORD)
|
||||
rv = self.login('adminx', 'default')
|
||||
assert 'Invalid username' in rv.data
|
||||
rv = self.login(flaskr.USERNAME, flaskr.PASSWORD + 'x')
|
||||
rv = self.login('admin', 'defaultx')
|
||||
assert 'Invalid password' in rv.data
|
||||
|
||||
Test Adding Messages
|
||||
|
|
@ -167,7 +167,7 @@ Now we can also test that adding messages works. Add a new test method
|
|||
like this::
|
||||
|
||||
def test_messages(self):
|
||||
self.login(flaskr.USERNAME, flaskr.PASSWORD)
|
||||
self.login('admin', 'default')
|
||||
rv = self.app.post('/add', data=dict(
|
||||
title='<Hello>',
|
||||
text='<strong>HTML</strong> allowed here'
|
||||
|
|
@ -214,3 +214,7 @@ functions. Here a full example that showcases this::
|
|||
assert flask.request.args['name'] == 'Peter'
|
||||
|
||||
All the other objects that are context bound can be used the same.
|
||||
|
||||
If you want to test your application with different configurations and
|
||||
there does not seem to be a good way to do that, consider switching to
|
||||
application factories (see :ref:`app-factories`).
|
||||
|
|
|
|||
|
|
@ -26,12 +26,27 @@ the values from there.
|
|||
PASSWORD = 'default'
|
||||
|
||||
Next we can create our actual application and initialize it with the
|
||||
config::
|
||||
config from the same file::
|
||||
|
||||
# create our little application :)
|
||||
app = Flask(__name__)
|
||||
app.secret_key = SECRET_KEY
|
||||
app.debug = DEBUG
|
||||
app.config.from_object(__name__)
|
||||
|
||||
:meth:`~flask.Config.from_object` will look at the given object (if it's a
|
||||
string it will import it) and then look for all uppercase variables
|
||||
defined there. In our case, the configuration we just wrote a few lines
|
||||
of code above. You can also move that into a separate file.
|
||||
|
||||
It is also a good idea to be able to load a configuration from a
|
||||
configurable file. This is what :meth:`~flask.Config.from_envvar` can
|
||||
do::
|
||||
|
||||
app.config.from_envvar('FLASKR_SETTINGS', silent=True)
|
||||
|
||||
That way someone can set an environment variable called
|
||||
:envvar:`FLASKR_SETTINGS` to specify a config file to be loaded which will
|
||||
then override the default values. The silent switch just tells Flask to
|
||||
not complain if no such environment key is set.
|
||||
|
||||
The `secret_key` is needed to keep the client-side sessions secure.
|
||||
Choose that key wisely and as hard to guess and complex as possible. The
|
||||
|
|
@ -46,7 +61,7 @@ Python shell or a script. This will come in handy later
|
|||
::
|
||||
|
||||
def connect_db():
|
||||
return sqlite3.connect(DATABASE)
|
||||
return sqlite3.connect(app.config['DATABASE'])
|
||||
|
||||
Finally we just add a line to the bottom of the file that fires up the
|
||||
server if we run that file as standalone application::
|
||||
|
|
|
|||
|
|
@ -63,9 +63,9 @@ notified about that and the user asked again::
|
|||
def login():
|
||||
error = None
|
||||
if request.method == 'POST':
|
||||
if request.form['username'] != USERNAME:
|
||||
if request.form['username'] != app.config['USERNAME']:
|
||||
error = 'Invalid username'
|
||||
elif request.form['password'] != PASSWORD:
|
||||
elif request.form['password'] != app.config['PASSWORD']:
|
||||
error = 'Invalid password'
|
||||
else:
|
||||
session['logged_in'] = True
|
||||
|
|
|
|||
56
docs/upgrading.rst
Normal file
56
docs/upgrading.rst
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
Upgrading to Newer Releases
|
||||
===========================
|
||||
|
||||
Flask itself is changing like any software is changing over time. Most of
|
||||
the changes are the nice kind, the kind where you don't have th change
|
||||
anything in your code to profit from a new release.
|
||||
|
||||
However every once in a while there are changes that do require some
|
||||
changes in your code or there are changes that make it possible for you to
|
||||
improve your own code quality by taking advantage of new features in
|
||||
Flask.
|
||||
|
||||
This section of the documentation enumerates all the changes in Flask from
|
||||
release to release and how you can change your code to have a painless
|
||||
updating experience.
|
||||
|
||||
Version 0.5
|
||||
-----------
|
||||
|
||||
Flask 0.5 introduces configuration support and logging as well as
|
||||
categories for flashing messages. All these are features that are 100%
|
||||
backwards compatible but you might want to take advantage of them.
|
||||
|
||||
Configuration Support
|
||||
`````````````````````
|
||||
|
||||
The configuration support makes it easier to write any kind of application
|
||||
that requires some sort of configuration. (Which most likely is the case
|
||||
for any application out there).
|
||||
|
||||
If you previously had code like this::
|
||||
|
||||
app.debug = DEBUG
|
||||
app.secret_key = SECRET_KEY
|
||||
|
||||
You no longer have to do that, instead you can just load a configuration
|
||||
into the config object. How this works is outlined in :ref:`config`.
|
||||
|
||||
Logging Integration
|
||||
```````````````````
|
||||
|
||||
Flask now configures a logger for you with some basic and useful defaults.
|
||||
If you run your application in production and want to profit from
|
||||
automatic error logging, you might be interested in attaching a proper log
|
||||
handler. Also you can start logging warnings and errors into the logger
|
||||
when appropriately. For more information on that, read
|
||||
:ref:`application-errors`.
|
||||
|
||||
Categories for Flash Messages
|
||||
`````````````````````````````
|
||||
|
||||
Flash messages can now have categories attached. This makes it possible
|
||||
to render errors, warnings or regular messages differently for example.
|
||||
This is an opt-in feature because it requires some rethinking in the code.
|
||||
|
||||
Read all about that in the :ref:`message-flashing-pattern` pattern.
|
||||
|
|
@ -10,7 +10,9 @@
|
|||
|
||||
~ How do I use it?
|
||||
|
||||
1. edit the configuration in the flaskr.py file
|
||||
1. edit the configuration in the flaskr.py file or
|
||||
export an FLASKR_SETTINGS environment variable
|
||||
pointing to a configuration file.
|
||||
|
||||
2. fire up a python shell and run this:
|
||||
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@ PASSWORD = 'default'
|
|||
|
||||
# create our little application :)
|
||||
app = Flask(__name__)
|
||||
app.secret_key = SECRET_KEY
|
||||
app.debug = DEBUG
|
||||
app.config.from_object(__name__)
|
||||
app.config.from_envvar('FLASKR_SETTINGS', silent=True)
|
||||
|
||||
|
||||
def connect_db():
|
||||
"""Returns a new connection to the database."""
|
||||
return sqlite3.connect(DATABASE)
|
||||
return sqlite3.connect(app.config['DATABASE'])
|
||||
|
||||
|
||||
def init_db():
|
||||
|
|
@ -76,9 +76,9 @@ def add_entry():
|
|||
def login():
|
||||
error = None
|
||||
if request.method == 'POST':
|
||||
if request.form['username'] != USERNAME:
|
||||
if request.form['username'] != app.config['USERNAME']:
|
||||
error = 'Invalid username'
|
||||
elif request.form['password'] != PASSWORD:
|
||||
elif request.form['password'] != app.config['PASSWORD']:
|
||||
error = 'Invalid password'
|
||||
else:
|
||||
session['logged_in'] = True
|
||||
|
|
|
|||
|
|
@ -18,14 +18,14 @@ class FlaskrTestCase(unittest.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
"""Before each test, set up a blank database"""
|
||||
self.db_fd, flaskr.DATABASE = tempfile.mkstemp()
|
||||
self.db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp()
|
||||
self.app = flaskr.app.test_client()
|
||||
flaskr.init_db()
|
||||
|
||||
def tearDown(self):
|
||||
"""Get rid of the database again after each test."""
|
||||
os.close(self.db_fd)
|
||||
os.unlink(flaskr.DATABASE)
|
||||
os.unlink(flaskr.app.config['DATABASE'])
|
||||
|
||||
def login(self, username, password):
|
||||
return self.app.post('/login', data=dict(
|
||||
|
|
@ -45,18 +45,22 @@ class FlaskrTestCase(unittest.TestCase):
|
|||
|
||||
def test_login_logout(self):
|
||||
"""Make sure login and logout works"""
|
||||
rv = self.login(flaskr.USERNAME, flaskr.PASSWORD)
|
||||
rv = self.login(flaskr.app.config['USERNAME'],
|
||||
flaskr.app.config['PASSWORD'])
|
||||
assert 'You were logged in' in rv.data
|
||||
rv = self.logout()
|
||||
assert 'You were logged out' in rv.data
|
||||
rv = self.login(flaskr.USERNAME + 'x', flaskr.PASSWORD)
|
||||
rv = self.login(flaskr.app.config['USERNAME'] + 'x',
|
||||
flaskr.app.config['PASSWORD'])
|
||||
assert 'Invalid username' in rv.data
|
||||
rv = self.login(flaskr.USERNAME, flaskr.PASSWORD + 'x')
|
||||
rv = self.login(flaskr.app.config['USERNAME'],
|
||||
flaskr.app.config['PASSWORD'] + 'x')
|
||||
assert 'Invalid password' in rv.data
|
||||
|
||||
def test_messages(self):
|
||||
"""Test that messages work"""
|
||||
self.login(flaskr.USERNAME, flaskr.PASSWORD)
|
||||
self.login(flaskr.app.config['USERNAME'],
|
||||
flaskr.app.config['PASSWORD'])
|
||||
rv = self.app.post('/add', data=dict(
|
||||
title='<Hello>',
|
||||
text='<strong>HTML</strong> allowed here'
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@
|
|||
|
||||
~ How do I use it?
|
||||
|
||||
1. edit the configuration in the minitwit.py file
|
||||
1. edit the configuration in the minitwit.py file or
|
||||
export an MINITWIT_SETTINGS environment variable
|
||||
pointing to a configuration file.
|
||||
|
||||
2. fire up a python shell and run this:
|
||||
|
||||
|
|
|
|||
|
|
@ -27,11 +27,13 @@ SECRET_KEY = 'development key'
|
|||
|
||||
# create our little application :)
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(__name__)
|
||||
app.config.from_envvar('MINITWIT_SETTINGS', silent=True)
|
||||
|
||||
|
||||
def connect_db():
|
||||
"""Returns a new connection to the database."""
|
||||
return sqlite3.connect(DATABASE)
|
||||
return sqlite3.connect(app.config['DATABASE'])
|
||||
|
||||
|
||||
def init_db():
|
||||
|
|
@ -237,12 +239,9 @@ def logout():
|
|||
return redirect(url_for('public_timeline'))
|
||||
|
||||
|
||||
# add some filters to jinja and set the secret key and debug mode
|
||||
# from the configuration.
|
||||
# add some filters to jinja
|
||||
app.jinja_env.filters['datetimeformat'] = format_datetime
|
||||
app.jinja_env.filters['gravatar'] = gravatar_url
|
||||
app.secret_key = SECRET_KEY
|
||||
app.debug = DEBUG
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -18,14 +18,14 @@ class MiniTwitTestCase(unittest.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
"""Before each test, set up a blank database"""
|
||||
self.db_fd, minitwit.DATABASE = tempfile.mkstemp()
|
||||
self.db_fd, minitwit.app.config['DATABASE'] = tempfile.mkstemp()
|
||||
self.app = minitwit.app.test_client()
|
||||
minitwit.init_db()
|
||||
|
||||
def tearDown(self):
|
||||
"""Get rid of the database again after each test."""
|
||||
os.close(self.db_fd)
|
||||
os.unlink(minitwit.DATABASE)
|
||||
os.unlink(minitwit.app.config['DATABASE'])
|
||||
|
||||
# helper functions
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue