首页 > 代码库 > flask - 1

flask - 1

from flask import Flask
app = Flask(__name__)

@app.route(/)
def hello_world():
    return Hello, World!

启动Server:

$ export FLASK_APP=hello.py
$ flask run
 * Running on http://127.0.0.1:5000/

或者:

$ export FLASK_APP=hello.py
$ python -m flask run
 * Running on http://127.0.0.1:5000/

在 Windows 中,用 set 替代 export 来设置环境变量。

在 Powershell中,设置环境变量如下:

$env:FLASK_APP="hello.py"

若要监听所有公共IP地址:

flask run --host=0.0.0.0

启动Debug模式:

$ export FLASK_DEBUG=1
$ flask run

This does the following things:

  1. it activates the debugger
  2. it activates the automatic reloader
  3. it enables the debug mode on the Flask application.

(在 window 中,用 set 替代 export 来设置环境变量)

路由URL:

the route() decorator is used to bind a function to a URL. Here are some basic examples:

@app.route(/)
def index():
    return Index Page

@app.route(/hello)
def hello():
    return Hello, World

To add variable parts to a URL you can mark these special sections as <variable_name>. Such a part is then passed as a keyword argument to your function. Optionally a converter can be used by specifying a rule with <converter:variable_name>. Here are some nice examples:

@app.route(/user/<username>)
def show_user_profile(username):
    # show the user profile for that user
    return User %s % username

@app.route(/post/<int:post_id>)
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return Post %d % post_id

 The following converters exist:

”String“ - accepts any text without a slash (the default)

”int“ - accepts integers

”float“ - like int but for floating point values

”path“ - like the default but also accepts slashes

”any“ - matches one of the items provided

”uuid“ - accepts UUID strings

Unique URLs / Redirection Behavior

@app.route(/projects/)
def projects():
    return The project page

@app.route(/about)
def about():
    return The about page

Though they look rather similar, they differ in their use of the trailing slash in the URLdefinition. In the first case, the canonical URL for the projects endpoint has a trailing slash. In that sense, it is similar to a folder on a filesystem. Accessing it without a trailing slash will cause Flask to redirect to the canonical URL with the trailing slash.

In the second case, however, the URL is defined without a trailing slash, rather like the pathname of a file on UNIX-like systems. Accessing the URL with a trailing slash will produce a 404 “Not Found” error.

This behavior allows relative URLs to continue working even if the trailing slash is omitted, consistent with how Apache and other servers work. Also, the URLs will stay unique, which helps search engines avoid indexing the same page twice.

URL Building

To build a URL to a specific function you can use the url_for() function. It accepts the name of the function as first argument and a number of keyword arguments, each corresponding to the variable part of the URL rule. Unknown variable parts are appended to the URL as query parameters.

>>> from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route(/)
... def index(): pass
...
>>> @app.route(/login)
... def login(): pass
...
>>> @app.route(/user/<username>)
... def profile(username): pass
...
>>> with app.test_request_context():
...  print url_for(index)
...  print url_for(login)
...  print url_for(login, next=/)
...  print url_for(profile, username=John Doe)
...
/
/login
/login?next=/
/user/John%20Doe

HTTP Method

HTTP (the protocol web applications are speaking) knows different methods for accessing URLs. By default, a route only answers to GET requests, but that can be changed by providing the methods argument to the route() decorator. Here are some examples:

from flask import request

@app.route(/login, methods=[GET, POST])
def login():
    if request.method == POST:
        do_the_login()
    else:
        show_the_login_form()

The following methods are very common:

GET
The browser tells the server to just get the information stored on that page and send it. This is probably the most common method.
HEAD
The browser tells the server to get the information, but it is only interested in theheaders, not the content of the page. An application is supposed to handle that as if a GET request was received but to not deliver the actual content. In Flask you don’t have to deal with that at all, the underlying Werkzeug library handles that for you.
POST
The browser tells the server that it wants to post some new information to that URL and that the server must ensure the data is stored and only stored once. This is how HTML forms usually transmit data to the server.
PUT
Similar to POST but the server might trigger the store procedure multiple times by overwriting the old values more than once. Now you might be asking why this is useful, but there are some good reasons to do it this way. Consider that the connection is lost during transmission: in this situation a system between the browser and the server might receive the request safely a second time without breaking things. With POST that would not be possible because it must only be triggered once.
DELETE
Remove the information at the given location.
OPTIONS
Provides a quick way for a client to figure out which methods are supported by this URL. Starting with Flask 0.6, this is implemented for you automatically.

Now the interesting part is that in HTML4 and XHTML1, the only methods a form can submit to the server are GET and POST. But with JavaScript and future HTML standards you can use the other methods as well. Furthermore HTTP has become quite popular lately and browsers are no longer the only clients that are using HTTP. For instance, many revision control systems use it.

Static Files

ust create a folder called staticin your package or next to your module and it will be available at /static on the application.

To generate URLs for static files, use the special ‘static‘ endpoint name:

url_for(static, filename=style.css)

The file has to be stored on the filesystem as static/style.css.

Rendering Templates

To render a template you can use the render_template() method. All you have to do is provide the name of the template and the variables you want to pass to the template engine as keyword arguments. Here’s a simple example of how to render a template:

from flask import render_template

@app.route(/hello/)
@app.route(/hello/<name>)
def hello(name=None):
    return render_template(hello.html, name=name)

Flask will look for templates in the templates folder. So if your application is a module, this folder is next to that module, if it’s a package it’s actually inside your package:

Case 1: a module:

/application.py
/templates
    /hello.html

Case 2: a package:

/application
    /__init__.py
    /templates
        /hello.html

For templates you can use the full power of Jinja2 templates.

Here is an example template:

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello, World!</h1>
{% endif %}

Inside templates you also have access to the requestsession and g objects as well as the get_flashed_messages() function.

Templates are especially useful if inheritance is used. Basically template inheritance makes it possible to keep certain elements on each page (like header, navigation and footer).

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 Markup class or by using the |safe filter in the template. 

Here is a basic introduction to how the Markup class works:

>>> from flask import Markup
>>> Markup(<strong>Hello %s!</strong>) % <blink>hacker</blink>
Markup(u<strong>Hello &lt;blink&gt;hacker&lt;/blink&gt;!</strong>)
>>> Markup.escape(<blink>hacker</blink>)
Markup(u&lt;blink&gt;hacker&lt;/blink&gt;)
>>> Markup(<em>Marked up</em> &raquo; HTML).striptags()
uMarked up \xbb HTML

Accessing Request Data

Context Locals

Certain objects in Flask are global objects, but not of the usual kind. These objects are actually proxies to objects that are local to a specific context. What a mouthful. But that is actually quite easy to understand.

Imagine the context being the handling thread. A request comes in and the web server decides to spawn a new thread (or something else, the underlying object is capable of dealing with concurrency systems other than threads). When Flask starts its internal request handling it figures out that the current thread is the active context and binds the current application and the WSGI environments to that context (thread). It does that in an intelligent way so that one application can invoke another application without breaking.

So what does this mean to you? Basically you can completely ignore that this is the case unless you are doing something like unit testing. You will notice that code which depends on a request object will suddenly break because there is no request object. The solution is creating a request object yourself and binding it to the context. The easiest solution for unit testing is to use the test_request_context() context manager. In combination with the with statement it will bind a test request so that you can interact with it. Here is an example:

from flask import request

with app.test_request_context(/hello, method=POST):
    # now you can do something with the request until the
    # end of the with block, such as basic assertions:
    assert request.path == /hello
    assert request.method == POST

The other possibility is passing a whole WSGI environment to the request_context()method:

from flask import request

with app.request_context(environ):
    assert request.method == POST

The Request Object

from flask import request

@app.route(/login, methods=[POST, GET])
def login():
    error = None
    if request.method == POST:
        if valid_login(request.form[username],
                       request.form[password]):
            return log_the_user_in(request.form[username])
        else:
            error = Invalid username/password
    # the code below is executed if the request method
    # was GET or the credentials were invalid
    return render_template(login.html, error=error)

To access parameters submitted in the URL (?key=value) you can use the argsattribute:

searchword = request.args.get(key, ‘‘)

File Uploads

You can handle uploaded files with Flask easily. Just make sure not to forget to set theenctype="multipart/form-data" attribute on your HTML form, otherwise the browser will not transmit your files at all.

from flask import request

@app.route(/upload, methods=[GET, POST])
def upload_file():
    if request.method == POST:
        f = request.files[the_file]
        f.save(/var/www/uploads/uploaded_file.txt)
    ...
from flask import request
from werkzeug.utils import secure_filename

@app.route(/upload, methods=[GET, POST])
def upload_file():
    if request.method == POST:
        f = request.files[the_file]
        f.save(/var/www/uploads/ + secure_filename(f.filename))
    ...

Cookies

Read cookies:

from flask import request

@app.route(/)
def index():
    username = request.cookies.get(username)
    # use cookies.get(key) instead of cookies[key] to not get a
    # KeyError if the cookie is missing.

Storing cookies:

from flask import make_response

@app.route(/)
def index():
    resp = make_response(render_template(...))
    resp.set_cookie(username, the username)
    return resp

Note that cookies are set on response objects. Since you normally just return strings from the view functions Flask will convert them into response objects for you. If you explicitly want to do that you can use the make_response() function and then modify it.

Redirects and Errors

To redirect a user to another endpoint, use the redirect() function; to abort a request early with an error code, use the abort() function:

from flask import abort, redirect, url_for

@app.route(/)
def index():
    return redirect(url_for(login))

@app.route(/login)
def login():
    abort(401)
    this_is_never_executed()

By default a black and white error page is shown for each error code. If you want to customize the error page, you can use the errorhandler() decorator:

from flask import render_template

@app.errorhandler(404)
def page_not_found(error):
    return render_template(page_not_found.html), 404

About Responses

The return value from a view function is automatically converted into a response object for you. If the return value is a string it’s converted into a response object with the string as response body, a 200 OK status code and a text/html mimetype. The logic that Flask applies to converting return values into response objects is as follows:

  1. If a response object of the correct type is returned it’s directly 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 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.

If you want to get hold of the resulting response object inside the view you can use themake_response() function.

Imagine you have a view like this:

@app.errorhandler(404)
def not_found(error):
    return render_template(error.html), 404

You just need to wrap the return expression with make_response() and get the response object to modify it, then return it:

@app.errorhandler(404)
def not_found(error):
    resp = make_response(render_template(error.html), 404)
    resp.headers[X-Something] = A value
    return resp

Sessions

In addition to the request object there is also a second object called session which allows you to store information specific to a user from one request to the next. This is implemented on top of cookies for you and signs the cookies cryptographically. What this means is that the user could look at the contents of your cookie but not modify it, 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__)

@app.route(/)
def index():
    if username in session:
        return Logged in as %s % escape(session[username])
    return You are not logged in

@app.route(/login, methods=[GET, POST])
def login():
    if request.method == POST:
        session[username] = request.form[username]
        return redirect(url_for(index))
    return ‘‘‘
        <form action="" method="post">
            <p><input type=text name=username>
            <p><input type=submit value=http://www.mamicode.com/Login>>‘‘‘

@app.route(/logout)
def logout():
    # remove the username from the session if it‘s there
    session.pop(username, None)
    return redirect(url_for(index))

# set the secret key.  keep this really secret:
app.secret_key = A0Zr98j/3yX R~XHH!jmN]LWX/,?RT

The escape() mentioned here does escaping for you if you are not using the template engine (as in this example).

How to generate the good secret keys:

The problem with random is that it’s hard to judge what is truly random. And a secret key should be as random as possible. Your operating system has ways to generate pretty random stuff based on a cryptographic random generator which can be used to get such a key:

>>> import os
>>> os.urandom(24)
\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8

A note on cookie-based sessions: Flask will take the values you put into the session object and serialize them into a cookie. If you are finding some values do not persist across requests, cookies are indeed enabled, and you are not getting a clear error message, check the size of the cookie in your page responses compared to the size supported by web browsers.

Message Flashing

Good applications and user interfaces are all about feedback. If the user does not get enough feedback they will probably end up hating the application. Flask provides a really simple way to give feedback to a user with the flashing system. The flashing system basically makes it possible to record a message at the end of a request and access it on the next (and only the next) request. This is usually combined with a layout template to expose the message.

To flash a message use the flash() method, to get hold of the messages you can useget_flashed_messages() which is also available in the templates.

Logging

app.logger.debug(A value for debugging)
app.logger.warning(A warning occurred (%d apples), 42)
app.logger.error(An error occurred)

Hooking in WSGI Middlewares

If you want to add a WSGI middleware to your application you can wrap the internal WSGI application. For example if you want to use one of the middlewares from the Werkzeug package to work around bugs in lighttpd, you can do it like this:

from werkzeug.contrib.fixers import LighttpdCGIRootFix
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)

Using Flask Extensions

Extensions are packages that help you accomplish common tasks. For example, Flask-SQLAlchemy provides SQLAlchemy support that makes it simple and easy to use with Flask.

For more on Flask extensions, have a look at Flask Extensions.

Deploying to a Web Server

Ready to deploy your new Flask app? Go to Deployment Options.

flask - 1