diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 1a8e17c6..1164e2b8 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -3,48 +3,59 @@ Quickstart ========== -Eager to get started? This page gives a good introduction to Flask. It -assumes you already have Flask installed. If you do not, head over to the -:ref:`installation` section. +Eager to get started? This page gives a good introduction to Flask. +Follow :doc:`installation` to set up a project and install Flask first. A Minimal Application --------------------- -A minimal Flask application looks something like this:: +A minimal Flask application looks something like this: + +.. code-block:: python from flask import Flask + from markupsafe import escape + app = Flask(__name__) - @app.route('/') + @app.route("/") def hello_world(): - return 'Hello, World!' + return f"

Hello, {escape(name)}!

" So what did that code do? -1. First we imported the :class:`~flask.Flask` class. An instance of this - class will be our WSGI application. -2. Next we create an instance of this class. The first argument is the name of - the application's module or package. If you are using a single module (as - in this example), you should use ``__name__`` because depending on if it's - started as application or imported as module the name will be different - (``'__main__'`` versus the actual import name). This is needed so that - Flask knows where to look for templates, static files, and so on. For more - information have a look at the :class:`~flask.Flask` documentation. -3. We then use the :meth:`~flask.Flask.route` decorator to tell Flask what URL - should trigger our function. -4. The function is given a name which is also used to generate URLs for that - particular function, and returns the message we want to display in the - user's browser. +1. First we imported the :class:`~flask.Flask` class. An instance of + this class will be our WSGI application. +2. Next we create an instance of this class. The first argument is the + name of the application's module or package. ``__name__`` is a + convenient shortcut for this that is appropriate for most cases. + This is needed so that Flask knows where to look for resources such + as templates and static files. +3. We then use the :meth:`~flask.Flask.route` decorator to tell Flask + what URL should trigger our function. +4. The function returns the message we want to display in the user's + browser. The default content type is HTML, so HTML in the string + will be rendered by the browser. -Just save it as :file:`hello.py` or something similar. Make sure to not call +.. note:: HTML escaping + + When returning HTML (the default response type in Flask), any user + input rendered in the output must be escaped to protect from + injection attacks. HTML templates in Jinja, introduced later, will + do this automatically. :func:`~markupsafe.escape`, shown above, can + be used manually. It's omitted for brevity in the examples below. + +Save it as :file:`hello.py` or something similar. Make sure to not call your application :file:`flask.py` because this would conflict with Flask itself. -To run the application you can either use the :command:`flask` command or -python's ``-m`` switch with Flask. Before you can do that you need +To run the application, use the :command:`flask` command or +:command:`python -m flask`. Before you can do that you need to tell your terminal the application to work with by exporting the -``FLASK_APP`` environment variable:: +``FLASK_APP`` environment variable: + +.. code-block:: text $ export FLASK_APP=hello.py $ flask run @@ -59,12 +70,6 @@ And on PowerShell:: PS C:\path\to\app> $env:FLASK_APP = "hello.py" -Alternatively you can use :command:`python -m flask`:: - - $ export FLASK_APP=hello.py - $ python -m flask run - * Running on http://127.0.0.1:5000/ - This launches a very simple builtin server, which is good enough for testing but probably not what you want to use in production. For deployment options see :ref:`deployment`. @@ -203,17 +208,17 @@ of the argument like ````. :: @app.route('/user/') def show_user_profile(username): # show the user profile for that user - return 'User %s' % escape(username) + return f'User {username}' @app.route('/post/') def show_post(post_id): # show the post with the given id, the id is an integer - return 'Post %d' % post_id + return f'Post {post_id}' @app.route('/path/') def show_subpath(subpath): # show the subpath after /path/ - return 'Subpath %s' % escape(subpath) + return f'Subpath {subpath}' Converter types: @@ -281,9 +286,7 @@ Python shell. See :ref:`context-locals`. .. code-block:: python - from flask import Flask, escape, url_for - - app = Flask(__name__) + from flask import url_for @app.route('/') def index(): @@ -295,7 +298,7 @@ Python shell. See :ref:`context-locals`. @app.route('/user/') def profile(username): - return '{}\'s profile'.format(escape(username)) + return f'{username}\'s profile' with app.test_request_context(): print(url_for('index')) @@ -416,12 +419,12 @@ Automatic escaping is enabled, so if ``name`` contains HTML it will be escaped automatically. If you can trust a variable and you know that it will be safe HTML (for example because it came from a module that converts wiki markup to HTML) you can mark it as safe by using the -:class:`~jinja2.Markup` class or by using the ``|safe`` filter in the +:class:`~markupsafe.Markup` class or by using the ``|safe`` filter in the template. Head over to the Jinja 2 documentation for more examples. Here is a basic introduction to how the :class:`~jinja2.Markup` class works:: - >>> from flask import Markup + >>> from markupsafe import Markup >>> Markup('Hello %s!') % 'hacker' Markup(u'Hello <blink>hacker</blink>!') >>> Markup.escape('hacker') @@ -495,8 +498,6 @@ test request so that you can interact with it. Here is an example:: The other possibility is passing a whole WSGI environment to the :meth:`~flask.Flask.request_context` method:: - from flask import request - with app.request_context(environ): assert request.method == 'POST' @@ -582,7 +583,6 @@ of the client to store the file on the server, pass it through the :func:`~werkzeug.utils.secure_filename` function that Werkzeug provides for you:: - from flask import request from werkzeug.utils import secure_filename @app.route('/upload', methods=['GET', 'POST']) @@ -706,6 +706,8 @@ you can use the :func:`~flask.make_response` function. Imagine you have a view like this:: + from flask import render_template + @app.errorhandler(404) def not_found(error): return render_template('error.html'), 404 @@ -714,6 +716,8 @@ You just need to wrap the return expression with :func:`~flask.make_response` and get the response object to modify it, then return it:: + from flask import make_response + @app.errorhandler(404) def not_found(error): resp = make_response(render_template('error.html'), 404) @@ -747,6 +751,8 @@ more complex applications. .. code-block:: python + from flask import jsonify + @app.route("/users") def users_api(): users = get_all_users() @@ -768,9 +774,7 @@ unless they know the secret key used for signing. In order to use sessions you have to set a secret key. Here is how sessions work:: - from flask import Flask, session, redirect, url_for, escape, request - - app = Flask(__name__) + from flask import session # Set the secret key to some random bytes. Keep this really secret! app.secret_key = b'_5#y2L"F4Q8z\n\xec]/' @@ -778,7 +782,7 @@ sessions work:: @app.route('/') def index(): if 'username' in session: - return 'Logged in as %s' % escape(session['username']) + return f'Logged in as {session["username"]}' return 'You are not logged in' @app.route('/login', methods=['GET', 'POST']) @@ -799,9 +803,6 @@ sessions work:: session.pop('username', None) return redirect(url_for('index')) -The :func:`~flask.escape` mentioned here does escaping for you if you are -not using the template engine (as in this example). - .. admonition:: How to generate good secret keys A secret key should be as random as possible. Your operating system has