mirror of https://github.com/pallets/flask.git
Merge branch '1.0.x'
This commit is contained in:
commit
2236ba980c
|
|
@ -9,8 +9,9 @@ Support questions
|
|||
Please, don't use the issue tracker for this. Use one of the following
|
||||
resources for questions about your own code:
|
||||
|
||||
* The IRC channel ``#pocoo`` on FreeNode.
|
||||
* The IRC channel ``#python`` on FreeNode for more general questions.
|
||||
* The ``#get-help`` channel on our Discord chat: https://discord.gg/t6rrQZH
|
||||
* The IRC channel ``#pocoo`` on FreeNode is linked to Discord, but
|
||||
Discord is preferred.
|
||||
* The mailing list flask@python.org for long term discussion or larger issues.
|
||||
* Ask on `Stack Overflow`_. Search with Google first using:
|
||||
``site:stackoverflow.com flask {search term, exception message, etc.}``
|
||||
|
|
@ -81,14 +82,26 @@ First time setup
|
|||
Start coding
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- Create a branch to identify the issue you would like to work on (e.g.
|
||||
``2287-dry-test-suite``)
|
||||
- Create a branch to identify the issue you would like to work on. If
|
||||
you're submitting a bug or documentation fix, branch off of the
|
||||
latest ".x" branch::
|
||||
|
||||
git checkout -b your-branch-name origin/1.0.x
|
||||
|
||||
If you're submitting a feature addition or change, branch off of the
|
||||
"master" branch::
|
||||
|
||||
git checkout -b your-branch-name origin/master
|
||||
|
||||
- Using your favorite editor, make your changes, `committing as you go`_.
|
||||
- Try to follow `PEP8`_, but you may ignore the line length limit if following
|
||||
it would make the code uglier.
|
||||
- Include tests that cover any code changes you make. Make sure the test fails
|
||||
without your patch. `Run the tests. <contributing-testsuite_>`_.
|
||||
- Push your commits to GitHub and `create a pull request`_.
|
||||
- Push your commits to GitHub and `create a pull request`_ by using::
|
||||
|
||||
git push --set-upstream origin your-branch-name
|
||||
|
||||
- Celebrate 🎉
|
||||
|
||||
.. _committing as you go: https://dont-be-afraid-to-commit.readthedocs.io/en/latest/git/commandlinegit.html#commit-your-changes
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ Links
|
|||
* Test status: https://dev.azure.com/pallets/pallets/_build?definitionId=2
|
||||
|
||||
* Test coverage: https://codecov.io/gh/pallets/flask
|
||||
* Official chat: https://discord.gg/t6rrQZH
|
||||
|
||||
.. _WSGI: https://wsgi.readthedocs.io
|
||||
.. _Werkzeug: https://www.palletsprojects.com/p/werkzeug/
|
||||
|
|
|
|||
|
|
@ -726,7 +726,7 @@ requests, make sure the default route only handles ``GET``, as redirects
|
|||
can't preserve form data. ::
|
||||
|
||||
@app.route('/region/', defaults={'id': 1})
|
||||
@app.route('/region/<id>', methods=['GET', 'POST'])
|
||||
@app.route('/region/<int:id>', methods=['GET', 'POST'])
|
||||
def region(id):
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ Typically, an application context will have the same lifetime as a
|
|||
request.
|
||||
|
||||
See :doc:`/reqcontext` for more information about how the contexts work
|
||||
and the full lifecycle of a request.
|
||||
and the full life cycle of a request.
|
||||
|
||||
|
||||
Manually Push a Context
|
||||
|
|
|
|||
|
|
@ -97,6 +97,6 @@ Discuss with the community.
|
|||
|
||||
The Flask developers keep the framework accessible to users with codebases big
|
||||
and small. If you find an obstacle in your way, caused by Flask, don't hesitate
|
||||
to contact the developers on the mailinglist or IRC channel. The best way for
|
||||
to contact the developers on the mailing list or IRC channel. The best way for
|
||||
the Flask and Flask extension developers to improve the tools for larger
|
||||
applications is getting feedback from users.
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ was dispatched to any other admin blueprint endpoint.
|
|||
Error Handlers
|
||||
--------------
|
||||
|
||||
Blueprints support the errorhandler decorator just like the :class:`Flask`
|
||||
Blueprints support the ``errorhandler`` decorator just like the :class:`Flask`
|
||||
application object, so it is easy to make Blueprint-specific custom error
|
||||
pages.
|
||||
|
||||
|
|
@ -258,14 +258,13 @@ Here is an example for a "404 Page Not Found" exception::
|
|||
|
||||
Most errorhandlers will simply work as expected; however, there is a caveat
|
||||
concerning handlers for 404 and 405 exceptions. These errorhandlers are only
|
||||
invoked from an appropriate ``raise`` statement or a call to ``abort``
|
||||
in another of the blueprint's view functions; they are not invoked by,
|
||||
e.g., an invalid URL access. This is because the blueprint does not
|
||||
"own" a certain URL space, so the application instance has no way of
|
||||
knowing which blueprint errorhandler it should run if given an invalid URL.
|
||||
If you would like to execute different handling strategies for these errors
|
||||
based on URL prefixes, they may be defined at the application level using
|
||||
the ``request`` proxy object::
|
||||
invoked from an appropriate ``raise`` statement or a call to ``abort`` in another
|
||||
of the blueprint's view functions; they are not invoked by, e.g., an invalid URL
|
||||
access. This is because the blueprint does not "own" a certain URL space, so
|
||||
the application instance has no way of knowing which blueprint error handler it
|
||||
should run if given an invalid URL. If you would like to execute different
|
||||
handling strategies for these errors based on URL prefixes, they may be defined
|
||||
at the application level using the ``request`` proxy object::
|
||||
|
||||
@app.errorhandler(404)
|
||||
@app.errorhandler(405)
|
||||
|
|
|
|||
|
|
@ -68,9 +68,9 @@ parts:
|
|||
The ``create_app`` factory in ``hello`` is called with the string ``'dev'``
|
||||
as the argument.
|
||||
|
||||
If ``FLASK_APP`` is not set, the command will look for a file called
|
||||
:file:`wsgi.py` or :file:`app.py` and try to detect an application instance or
|
||||
factory.
|
||||
If ``FLASK_APP`` is not set, the command will try to import "app" or
|
||||
"wsgi" (as a ".py" file, or package) and try to detect an application
|
||||
instance or factory.
|
||||
|
||||
Within the given import, the command looks for an application instance named
|
||||
``app`` or ``application``, then any application instance. If no instance is
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ toggling the debug mode, setting the secret key, and other such
|
|||
environment-specific things.
|
||||
|
||||
The way Flask is designed usually requires the configuration to be
|
||||
available when the application starts up. You can hardcode the
|
||||
available when the application starts up. You can hard code the
|
||||
configuration in the code, which for many small applications is not
|
||||
actually that bad, but there are better ways.
|
||||
|
||||
|
|
@ -437,6 +437,7 @@ methods on the config object as well to load from individual files. For a
|
|||
complete reference, read the :class:`~flask.Config` object's
|
||||
documentation.
|
||||
|
||||
|
||||
Configuring from Environment Variables
|
||||
--------------------------------------
|
||||
|
||||
|
|
@ -448,15 +449,13 @@ Environment variables can be set on Linux or OS X with the export command in
|
|||
the shell before starting the server::
|
||||
|
||||
$ export SECRET_KEY='5f352379324c22463451387a0aec5d2f'
|
||||
$ export DEBUG=False
|
||||
$ export MAIL_ENABLED=false
|
||||
$ python run-app.py
|
||||
* Running on http://127.0.0.1:5000/
|
||||
* Restarting with reloader...
|
||||
|
||||
On Windows systems use the `set` builtin instead::
|
||||
On Windows systems use the ``set`` builtin instead::
|
||||
|
||||
> set SECRET_KEY='5f352379324c22463451387a0aec5d2f'
|
||||
> set DEBUG=False
|
||||
|
||||
While this approach is straightforward to use, it is important to remember that
|
||||
environment variables are strings -- they are not automatically deserialized
|
||||
|
|
@ -464,17 +463,15 @@ into Python types.
|
|||
|
||||
Here is an example of a configuration file that uses environment variables::
|
||||
|
||||
# Example configuration
|
||||
import os
|
||||
|
||||
ENVIRONMENT_DEBUG = os.environ.get("DEBUG", default=False)
|
||||
if ENVIRONMENT_DEBUG.lower() in ("f", "false"):
|
||||
ENVIRONMENT_DEBUG = False
|
||||
_mail_enabled = os.environ.get("MAIL_ENABLED", default="true")
|
||||
MAIL_ENABLED = _mail_enabled.lower() in {"1", "t", "true"}
|
||||
|
||||
SECRET_KEY = os.environ.get("SECRET_KEY")
|
||||
|
||||
DEBUG = ENVIRONMENT_DEBUG
|
||||
SECRET_KEY = os.environ.get("SECRET_KEY", default=None)
|
||||
if not SECRET_KEY:
|
||||
raise ValueError("No secret key set for Flask application")
|
||||
raise ValueError("No SECRET_KEY set for Flask application")
|
||||
|
||||
|
||||
Notice that any value besides an empty string will be interpreted as a boolean
|
||||
|
|
@ -486,6 +483,7 @@ ability to access the configuration when starting up. There are other methods
|
|||
on the config object as well to load from individual files. For a complete
|
||||
reference, read the :class:`~flask.Config` class documentation.
|
||||
|
||||
|
||||
Configuration Best Practices
|
||||
----------------------------
|
||||
|
||||
|
|
@ -496,7 +494,7 @@ that experience:
|
|||
|
||||
1. Create your application in a function and register blueprints on it.
|
||||
That way you can create multiple instances of your application with
|
||||
different configurations attached which makes unittesting a lot
|
||||
different configurations attached which makes unit testing a lot
|
||||
easier. You can use this to pass in configuration as needed.
|
||||
|
||||
2. Do not write code that needs the configuration at import time. If you
|
||||
|
|
@ -529,7 +527,7 @@ the config file by adding ``from yourapplication.default_settings
|
|||
import *`` to the top of the file and then overriding the changes by hand.
|
||||
You could also inspect an environment variable like
|
||||
``YOURAPPLICATION_MODE`` and set that to `production`, `development` etc
|
||||
and import different hardcoded files based on that.
|
||||
and import different hard-coded files based on that.
|
||||
|
||||
An interesting pattern is also to use classes and inheritance for
|
||||
configuration::
|
||||
|
|
|
|||
|
|
@ -23,9 +23,15 @@ For example, to run a Flask application with 4 worker processes (``-w
|
|||
|
||||
$ gunicorn -w 4 -b 127.0.0.1:4000 myproject:app
|
||||
|
||||
The ``gunicorn`` command expects the names of your application module or
|
||||
package and the application instance within the module. If you use the
|
||||
application factory pattern, you can pass a call to that::
|
||||
|
||||
$ gunicorn "myproject:create_app()"
|
||||
|
||||
.. _Gunicorn: https://gunicorn.org/
|
||||
.. _eventlet: https://eventlet.net/
|
||||
.. _greenlet: https://greenlet.readthedocs.io/en/latest/
|
||||
|
||||
|
||||
uWSGI
|
||||
--------
|
||||
|
|
@ -123,8 +129,8 @@ If your httpd is not providing these headers, the most common setup invokes the
|
|||
host being set from ``X-Forwarded-Host`` and the remote address from
|
||||
``X-Forwarded-For``::
|
||||
|
||||
from werkzeug.contrib.fixers import ProxyFix
|
||||
app.wsgi_app = ProxyFix(app.wsgi_app)
|
||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
|
||||
|
||||
.. admonition:: Trusting Headers
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ the time. There are ways to fake multiple applications with a single
|
|||
application object, like maintaining a stack of applications, but this
|
||||
causes some problems I won't outline here in detail. Now the question is:
|
||||
when does a microframework need more than one application at the same
|
||||
time? A good example for this is unittesting. When you want to test
|
||||
time? A good example for this is unit testing. When you want to test
|
||||
something it can be very helpful to create a minimal application to test
|
||||
specific behavior. When the application object is deleted everything it
|
||||
allocated will be freed again.
|
||||
|
|
@ -76,7 +76,7 @@ there are better ways to do that so that you do not lose the reference
|
|||
to the application object :meth:`~flask.Flask.wsgi_app`).
|
||||
|
||||
Furthermore this design makes it possible to use a factory function to
|
||||
create the application which is very helpful for unittesting and similar
|
||||
create the application which is very helpful for unit testing and similar
|
||||
things (:ref:`app-factories`).
|
||||
|
||||
The Routing System
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ also avoids having multiple developers working in isolation on pretty much the
|
|||
same problem.
|
||||
|
||||
Remember: good API design is hard, so introduce your project on the
|
||||
mailinglist, and let other developers give you a helping hand with
|
||||
mailing list, and let other developers give you a helping hand with
|
||||
designing the API.
|
||||
|
||||
The best Flask extensions are extensions that share common idioms for the
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Extensions
|
|||
Extensions are extra packages that add functionality to a Flask
|
||||
application. For example, an extension might add support for sending
|
||||
email or connecting to a database. Some extensions add entire new
|
||||
frameworks to help build certain types of applications, like a ReST API.
|
||||
frameworks to help build certain types of applications, like a REST API.
|
||||
|
||||
|
||||
Finding Extensions
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@ Adding HTTP Method Overrides
|
|||
============================
|
||||
|
||||
Some HTTP proxies do not support arbitrary HTTP methods or newer HTTP
|
||||
methods (such as PATCH). In that case it's possible to “proxy” HTTP
|
||||
methods (such as PATCH). In that case it's possible to "proxy" HTTP
|
||||
methods through another HTTP method in total violation of the protocol.
|
||||
|
||||
The way this works is by letting the client do an HTTP POST request and
|
||||
set the ``X-HTTP-Method-Override`` header and set the value to the
|
||||
intended HTTP method (such as ``PATCH``).
|
||||
set the ``X-HTTP-Method-Override`` header. Then the method is replaced
|
||||
with the header value before being passed to Flask.
|
||||
|
||||
This can easily be accomplished with an HTTP middleware::
|
||||
This can be accomplished with an HTTP middleware::
|
||||
|
||||
class HTTPMethodOverrideMiddleware(object):
|
||||
allowed_methods = frozenset([
|
||||
|
|
@ -29,13 +29,12 @@ This can easily be accomplished with an HTTP middleware::
|
|||
def __call__(self, environ, start_response):
|
||||
method = environ.get('HTTP_X_HTTP_METHOD_OVERRIDE', '').upper()
|
||||
if method in self.allowed_methods:
|
||||
method = method.encode('ascii', 'replace')
|
||||
environ['REQUEST_METHOD'] = method
|
||||
if method in self.bodyless_methods:
|
||||
environ['CONTENT_LENGTH'] = '0'
|
||||
return self.app(environ, start_response)
|
||||
|
||||
To use this with Flask this is all that is necessary::
|
||||
To use this with Flask, wrap the app object with the middleware::
|
||||
|
||||
from flask import Flask
|
||||
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ of the argument like ``<converter:variable_name>``. ::
|
|||
@app.route('/user/<username>')
|
||||
def show_user_profile(username):
|
||||
# show the user profile for that user
|
||||
return 'User %s' % username
|
||||
return 'User %s' % escape(username)
|
||||
|
||||
@app.route('/post/<int:post_id>')
|
||||
def show_post(post_id):
|
||||
|
|
@ -213,7 +213,7 @@ of the argument like ``<converter:variable_name>``. ::
|
|||
@app.route('/path/<path:subpath>')
|
||||
def show_subpath(subpath):
|
||||
# show the subpath after /path/
|
||||
return 'Subpath %s' % subpath
|
||||
return 'Subpath %s' % escape(subpath)
|
||||
|
||||
Converter types:
|
||||
|
||||
|
|
@ -281,7 +281,7 @@ Python shell. See :ref:`context-locals`.
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
from flask import Flask, url_for
|
||||
from flask import Flask, escape, url_for
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
|
@ -295,7 +295,7 @@ Python shell. See :ref:`context-locals`.
|
|||
|
||||
@app.route('/user/<username>')
|
||||
def profile(username):
|
||||
return '{}\'s profile'.format(username)
|
||||
return '{}\'s profile'.format(escape(username))
|
||||
|
||||
with app.test_request_context():
|
||||
print(url_for('index'))
|
||||
|
|
@ -690,10 +690,10 @@ response objects is as follows:
|
|||
returned from the view.
|
||||
2. If it's a string, a response object is created with that data and the
|
||||
default parameters.
|
||||
3. If a tuple is returned the items in the tuple can provide extra
|
||||
information. Such tuples have to be in the form ``(response, status,
|
||||
headers)`` or ``(response, headers)`` where at least one item has
|
||||
to be in the tuple. The ``status`` value will override the status code
|
||||
3. If a tuple is returned the items in the tuple can provide extra information.
|
||||
Such tuples have to be in the form ``(response, status, headers)``,
|
||||
``(response, headers)`` or ``(response, status)`` where at least one item
|
||||
has to be in the tuple. The ``status`` value will override the status code
|
||||
and ``headers`` can be a list or dictionary of additional header values.
|
||||
4. If none of that works, Flask will assume the return value is a
|
||||
valid WSGI application and convert that into a response object.
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ can you do?
|
|||
|
||||
This is where some helper functions come in handy. Keep in mind however
|
||||
that these functions are not only there for interactive shell usage, but
|
||||
also for unittesting and other situations that require a faked request
|
||||
also for unit testing and other situations that require a faked request
|
||||
context.
|
||||
|
||||
Generally it's recommended that you read the :ref:`request-context`
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ The Golden Rule
|
|||
So the rule of thumb: if you are not dealing with binary data, work with
|
||||
Unicode. What does working with Unicode in Python 2.x mean?
|
||||
|
||||
- as long as you are using ASCII charpoints only (basically numbers,
|
||||
some special characters of latin letters without umlauts or anything
|
||||
- as long as you are using ASCII code points only (basically numbers,
|
||||
some special characters of Latin letters without umlauts or anything
|
||||
fancy) you can use regular string literals (``'Hello World'``).
|
||||
- if you need anything else than ASCII in a string you have to mark
|
||||
this string as Unicode string by prefixing it with a lowercase `u`.
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ def has_request_context():
|
|||
self.remote_addr = remote_addr
|
||||
|
||||
Alternatively you can also just test any of the context bound objects
|
||||
(such as :class:`request` or :class:`g` for truthness)::
|
||||
(such as :class:`request` or :class:`g`) for truthness::
|
||||
|
||||
class User(db.Model):
|
||||
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ def url_for(endpoint, **values):
|
|||
:param values: the variable arguments of the URL rule
|
||||
:param _external: if set to ``True``, an absolute URL is generated. Server
|
||||
address can be changed via ``SERVER_NAME`` configuration variable which
|
||||
defaults to `localhost`.
|
||||
falls back to the `Host` header, then to the IP and port of the request.
|
||||
:param _scheme: a string specifying the desired URL scheme. The `_external`
|
||||
parameter must be set to ``True`` or a :exc:`ValueError` is raised. The default
|
||||
behavior uses the same scheme as the current request, or
|
||||
|
|
|
|||
Loading…
Reference in New Issue