Table of Contents
1.1 WSGI, web server gateway interface
1 Flask快速入门
1.1 WSGI, web server gateway interface
WSGI不是服务器,不是API,不是Python模块,更不是什么框架,而是一种服务器和客户端交互的接口规范!
在WSGI规范下,web组件被分成三类:client, server, and middleware.
WSGI apps(服从该规范的应用)能够被连接起来(be stacked)处理一个request,这也就引发了中间件这个概念,中间件同时实现c端和s端的接口,c看它是上游s,s看它是下游的c。
WSGI的s端所做的工作仅仅是接收请求,传给application(做处理),然后将结果response给middleware或client.除此以外的工作都交给中间件或者application来做。
1.2 A minimal application
- Debug mode:
$ export FLASK_DEBUG=1
$ flask run
- Routing:route() decorator is used to bind a function to URLs.
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello, World'
- Variables Rules:We can 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>.
@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
- Flask's URL rules are based o Werkzeug's routing module. The idea is to ensure beautiful and unique URLs.
| 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. |
| Like the pathname of a file on UNIX-like systems. Accessing the URL with a trailing slash will produce a 404 “Not Found” error. |
- URL Building
- url_for(): build a URL to a specific function .
- url_for(function name, variable part of the URL rule)
- Noted: unknown variable parts are appended to the URL as query parameters.
- Test_request_context(): tells Flask to behave as though it is handling a request, even though we are interacting with it through a Python shell.
- Why using url_for()?
- Reversing is often more descriptive than hard-coding the URLs. More importantly, it allows you to change URLs in one go, without having to remember to change URLs all over the place.
- URL building will handle escaping of special characters and Unicode data transparently for you, so you don’t have to deal with them.
- If your application is placed outside the URL root - say, in /myapplication instead of / - url_for() will handle that properly for you.
- url_for(): build a URL to a specific function .
- HTTP Methods
Route() : can also provide the HTTP method argument.
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
do_the_login()
else:
show_the_login_form()
- Reference - HTTP
- HTTP tells the server what the client want to do with the requested page. There are some common methods used by HTTP:
- 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 the headers, 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
- HTTP tells the server what the client want to do with the requested page. There are some common methods used by HTTP:
- Static files
- Rendering Templates: render_template(template_name, variables you want to pass to the template engine as keyword arguments)
Inside templates, you also have access to the request, session and g objects as well as the get_flashed_messages() function.
from flask import render_template
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
- Accessing Request Data - Context locals
- The request object:From flask import request
- File uploads
- 确保你没忘记在 HTML 表单中设置enctype="multipart/form-data" 属性
- Cookies
- Set_cookie()
- Redirect and error:To redirect a user to another endpoint, use the redirect() function; to abort a request early with an error code, use the abort() function:
- Session:除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名。这意味着用户可以查看你 Cookie 的内容,但却不能修改它,除非用户知道签名的密钥。
2 Flask Tutorial笔记
- 1. Create the folders
Static folder: are avaliable to users of application via HTTP. This is the place where CSS and javascript files go.
Templates Folder: where flask will look for Jinja2 templates
- 2. Database schema
Create a file named schema.sql in the flaskr/flaskr folder
The contents of the schema.sql are as follows:
Introduction: this consists of a single table called entries.
- 3. Application setup code
- 4. Database connection
- Flask provides two contexts, the application context and the request context. There are special variables that use these. For instance, the request variable is the request object associated with the current request context, whereas g is a general purpose variable associated with the current application context. You can store information safely on the g object.
- Functions marked with teardown_appcontext() are called every time the application context tears down. The application context is created before the request comes in and is destroyed (torn down) whenever the request finishes. A teardown can happen because of two reasons: either everything wet well (the error parameter will be none) or an exception happened, in which case the error is passed to the tear down function.
- The app.cli.command() registers a new command with the flask script. When the command executes, flask will automatically create an application context which is bound to the right applcation. Within this function, you can then access flask.g and other things as you might expect. When the script ends, the application context tears down and the database connection is released
- The open_resource() method of the application object is a convenient helper function that will open a resource that the application provides. This function opens a file from the resource location (the flaskr/flaskr folder) and allows you to read from it. It is used in this example to execute a script on the database connection.
- The connection object provided by SQLite can give you a cursor object. On that cursor, there is a method to execute a complete script. Finally, you only have to commit the changes. SQLite3 and other transactional databases will not commit unless you explicitly tell it to.
3 SQLALchemy
参考资料
http://blog.csdn.net/buster2014/article/details/50933081
http://www.jb51.net/article/49789.htm
简单介绍和案例
似乎ORM最难设计的部分是查询。特别是面向对象的查询,今天学习SQLAlchemy,发现SQLAlchemy的查询语法竟如此灵活,惊叹其如此强大的表达能力的同时也对Python也有了更深的认识。下面看一下我写的一些查询语句:
# 简单查询
# 注意User是一个类对象,user_table是数据库中的表
print(session.query(User).all())
# —相当于SQL语句—> select * from user_table
print(session.query(User.name,User.fullname.all()))
# —相当于SQL语句—> select user_table.name,user_table.fullname from user_table
print(session.query(User,user.name).all())
# —相当于SQL语句—> select user_table.name from user_table
# 条件查询
print (session.query(User).filter_by(name=’user1).all())
# —相当于SQL语句—> select * from user_table where name = ‘user1’
print (session.query(User).filter(User.name == “user).all())
# —相当于SQL语句—> select * from user_table where user_table.name = user
print (session.query(User).filter(User.name.like(“user%”)).all())
# —相当于SQL语句—> select * from user_table where user_table.name like user%
# 多条件查询
print (session.query(User).filter(and_(User.name.like(“user),User.fullname.like(“first%”))).all()
# —相当于SQL语句—>
# select * from user_table where user_table.name like %user and user_table.fullname # like first%
print (session.query(User).filter(or_(User.name.like(“user%),User.password != None)).all()
# —相当于SQL语句—>
# select * from user_table where user_table.name = user% or user_table.password != # none
# sql过滤
print (session(User).filter(“id>:id”).params(id=1).all()
# —相当于SQL语句—> select * from user_table where user_table.id > 1
# 关联查询
print (session.query(User,Address).filter(User.id == Address.user_id).all()
# —相当于SQL语句—>
# select * from user_table,address_table where user_table.id == address.user_id
print (session.query(User).jion(User.address).all()
print (session.query(User).outerjoin(User.address).all())
# 聚合查询
print (session.query(User.name,func.count(‘*’).label(“user_count)).group_by(User.name).all())
# —相当于SQL语句—>
# select count(user_table.name) as user_count
# from user_table where ... group by(user_table.name)
print (session.query(User.name,func.sum(User.id).label(“user_id_sum”)).group_by(User.name).all())
# —相当于SQL语句—>
# select user_table.name,sum(user_table.id) from user_table
# where group by(user_table.name)
# 子查询
stmt = session.query(Address.user_id,func.count(‘*’).label(“address_count”).group by(Address.user_id).subquery()
print (session.query(User,stmt.c.address_count).outjion((stmt,User.id == stmt.c.user_id.order_by(User_id).all()
# exits
print (session.query(User).filter(exists().where(Address.user_id == User.id)))
print (session.query(User).filter(User.addresses.any()))