Python Flask Web 框架入门(1)

mkdir HelloWorld/templates
touch HelloWorld/server.py


#### 4.2 列出所有的url参数


在server.py中添加以下内容:



from flask import Flask, request

app = Flask(name)

@app.route(‘/’)
def hello_world():
return request.args.str()

if name == ‘main’:
app.run(port=5000, debug=True)


在浏览器中访问`http://127.0.0.1:5000/?user=Flask&time&p=7&p=8`,将显示:



ImmutableMultiDict([(‘user’, ‘Flask’), (‘time’, ‘’), (‘p’, ‘7’), (‘p’, ‘8’)])


较新的浏览器也支持直接在url中输入中文(最新的火狐浏览器内部会帮忙将中文转换成符合URL规范的数据),在浏览器中访问`http://127.0.0.1:5000/?info=这是爱,`,将显示:



ImmutableMultiDict([(‘info’, ‘这是爱,’)])


浏览器传给我们的Flask服务的数据长什么样子呢?可以通过`request.full_path`和`request.path`来看一下:



from flask import Flask, request

app = Flask(name)

@app.route(‘/’)
def hello_world():
print(request.path)
print(request.full_path)
return request.args.str()

if name == ‘main’:
app.run(port=5000, debug=True)


浏览器访问`http://127.0.0.1:5000/?info=这是爱,`,运行`server.py`的终端会输出:



/
/?info=%E8%BF%99%E6%98%AF%E7%88%B1%EF%BC%8C


#### 4.3 获取某个指定的参数


例如,要获取键`info`对应的值,如下修改`server.py`:



from flask import Flask, request

app = Flask(name)

@app.route(‘/’)
def hello_world():
return request.args.get(‘info’)

if name == ‘main’:
app.run(port=5000)


运行`server.py`,在浏览器中访问`http://127.0.0.1:5000/?info=hello`,浏览器将显示:



hello


不过,当我们访问`http://127.0.0.1:5000/`时候却出现了500错误,浏览器显示:  
  


如果开启了Debug模式,会显示:  
  


为什么为这样?


这是因为没有在URL参数中找到`info`。所以`request.args.get('info')`返回Python内置的None,而Flask不允许返回None。


解决方法很简单,我们先判断下它是不是None:



from flask import Flask, request

app = Flask(name)

@app.route(‘/’)
def hello_world():
r = request.args.get(‘info’)
if r==None:
# do something
return ‘’
return r

if name == ‘main’:
app.run(port=5000, debug=True)


另外一个方法是,设置默认值,也就是取不到数据时用这个值:



from flask import Flask, request

app = Flask(name)

@app.route(‘/’)
def hello_world():
r = request.args.get(‘info’, ‘hi’)
return r

if name == ‘main’:
app.run(port=5000, debug=True)


函数`request.args.get`的第二个参数用来设置默认值。此时在浏览器访问`http://127.0.0.1:5000/`,将显示:



hi


#### 4.4 如何处理多值


还记得上面有一次请求是这样的吗? `http://127.0.0.1:5000/?user=Flask&time&p=7&p=8`,仔细看下,`p`有两个值。


如果我们的代码是:



from flask import Flask, request

app = Flask(name)

@app.route(‘/’)
def hello_world():
r = request.args.get(‘p’)
return r

if name == ‘main’:
app.run(port=5000, debug=True)


在浏览器中请求时,我们只会看到`7`。如果我们需要把`p`的所有值都获取到,该怎么办?


不用`get`,用`getlist`:



from flask import Flask, request

app = Flask(name)

@app.route(‘/’)
def hello_world():
r = request.args.getlist(‘p’) # 返回一个list
return str®

if name == ‘main’:
app.run(port=5000, debug=True)


浏览器输入 `http://127.0.0.1:5000/?user=Flask&time&p=7&p=8`,我们会看到`['7', '8']`。


#### 4.5 本节源码


[https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-002](https://bbs.csdn.net/topics/618317507)


### 5. 获取POST方法传送的数据


作为一种HTTP请求方法,POST用于向指定的资源提交要被处理的数据。我们在某网站注册用户、写文章等时候,需要将数据传递到网站服务器中。并不适合将数据放到URL参数中,密码放到URL参数中容易被看到,文章数据又太多,浏览器不一定支持太长长度的URL。这时,一般使用POST方法。


本文使用python的requests库模拟浏览器。


安装方法:



$ sudo pip3 install requests


#### 5.1 建立Flask项目


按照以下命令建立Flask项目HelloWorld:



mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py


#### 5.2 查看POST数据内容


以用户注册为例子,我们需要向服务器`/register`传送用户名`name`和密码`password`。如下编写`HelloWorld/server.py`。



from flask import Flask, request

app = Flask(name)

@app.route(‘/’)
def hello_world():
return ‘hello world’

@app.route(‘/register’, methods=[‘POST’])
def register():
print(request.headers)
print(request.stream.read())
return ‘welcome’

if name == ‘main’:
app.run(port=5000, debug=True)


[`@app.route](mailto:%60@app.route "`@app.route  ")(‘/register’, methods=[‘POST’])`是指url`/register`只接受POST方法。可以根据需要修改`methods`参数,例如如果想要让它同时支持GET和POST,这样写:



@app.route(‘/register’, methods=[‘GET’, ‘POST’])


浏览器模拟工具`client.py`内容如下:



import requests

user_info = {‘name’: ‘letian’, ‘password’: ‘123’}
r = requests.post(“http://127.0.0.1:5000/register”, data=user_info)

print(r.text)


运行`HelloWorld/server.py`,然后运行`client.py`。`client.py`将输出:



welcome


而`HelloWorld/server.py`在终端中输出以下调试信息(通过`print`输出):



Host: 127.0.0.1:5000
User-Agent: python-requests/2.19.1
Accept-Encoding: gzip, deflate
Accept: /
Connection: keep-alive
Content-Length: 24
Content-Type: application/x-www-form-urlencoded

b’name=letian&password=123’


前6行是client.py生成的HTTP请求头,由`print(request.headers)`输出。


请求体的数据,我们通过`print(request.stream.read())`输出,结果是:



b’name=letian&password=123’


#### 5.3 解析POST数据


上面,我们看到post的数据内容是:



b’name=letian&password=123’


我们要想办法把我们要的name、password提取出来,怎么做呢?自己写?不用,Flask已经内置了解析器`request.form`。


我们将服务代码改成:



from flask import Flask, request

app = Flask(name)

@app.route(‘/’)
def hello_world():
return ‘hello world’

@app.route(‘/register’, methods=[‘POST’])
def register():
print(request.headers)
# print(request.stream.read()) # 不要用,否则下面的form取不到数据
print(request.form)
print(request.form[‘name’])
print(request.form.get(‘name’))
print(request.form.getlist(‘name’))
print(request.form.get(‘nickname’, default=‘little apple’))
return ‘welcome’

if name == ‘main’:
app.run(port=5000, debug=True)


执行`client.py`请求数据,服务器代码会在终端输出:



Host: 127.0.0.1:5000
User-Agent: python-requests/2.19.1
Accept-Encoding: gzip, deflate
Accept: /
Connection: keep-alive
Content-Length: 24
Content-Type: application/x-www-form-urlencoded

ImmutableMultiDict([(‘name’, ‘letian’), (‘password’, ‘123’)])
letian
letian
[‘letian’]
little apple


`request.form`会自动解析数据。


`request.form['name']`和`request.form.get('name')`都可以获取`name`对应的值。对于`request.form.get()`可以为参数`default`指定值以作为默认值。所以:



print(request.form.get(‘nickname’, default=‘little apple’))


输出的是默认值



little apple


如果`name`有多个值,可以使用`request.form.getlist('name')`,该方法将返回一个列表。我们将client.py改一下:



import requests

user_info = {‘name’: [‘letian’, ‘letian2’], ‘password’: ‘123’}
r = requests.post(“http://127.0.0.1:5000/register”, data=user_info)

print(r.text)


此时运行`client.py`,`print(request.form.getlist('name'))`将输出:



[u’letian’, u’letian2’]


#### 5.4 本节源码


[https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-003](https://bbs.csdn.net/topics/618317507)


### 6. 处理和响应JSON数据


使用 HTTP POST 方法传到网站服务器的数据格式可以有很多种,比如「5. 获取POST方法传送的数据」讲到的`name=letian&password=123`这种用过`&`符号分割的key-value键值对格式。我们也可以用JSON格式、XML格式。相比XML的重量、规范繁琐,JSON显得非常小巧和易用。


#### 6.1 建立Flask项目


按照以下命令建立Flask项目HelloWorld:



mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py


#### 6.2 处理JSON格式的请求数据


如果POST的数据是JSON格式,`request.json`会自动将json数据转换成Python类型(字典或者列表)。


编写`server.py`:



from flask import Flask, request

app = Flask(“my-app”)

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

@app.route(‘/add’, methods=[‘POST’])
def add():
print(request.headers)
print(type(request.json))
print(request.json)
result = request.json[‘a’] + request.json[‘b’]
return str(result)

if name == ‘main’:
app.run(host=‘127.0.0.1’, port=5000, debug=True)


编写`client.py`模拟浏览器请求:



import requests

json_data = {‘a’: 1, ‘b’: 2}

r = requests.post(“http://127.0.0.1:5000/add”, json=json_data)

print(r.text)


运行`server.py`,然后运行`client.py`,`client.py` 会在终端输出:



3


`server.py` 会在终端输出:



Host: 127.0.0.1:5000
User-Agent: python-requests/2.19.1
Accept-Encoding: gzip, deflate
Accept: /
Connection: keep-alive
Content-Length: 16
Content-Type: application/json

<class ‘dict’>
{‘a’: 1, ‘b’: 2}


注意,请求头中`Content-Type`的值是`application/json`。


#### 6.3 响应JSON-方案1


响应JSON时,除了要把响应体改成JSON格式,响应头的`Content-Type`也要设置为`application/json`。


编写`server2.py`:



from flask import Flask, request, Response
import json

app = Flask(“my-app”)

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

@app.route(‘/add’, methods=[‘POST’])
def add():
result = {‘sum’: request.json[‘a’] + request.json[‘b’]}
return Response(json.dumps(result), mimetype=‘application/json’)

if name == ‘main’:
app.run(host=‘127.0.0.1’, port=5000, debug=True)


修改后运行。


编写`client2.py`:



import requests

json_data = {‘a’: 1, ‘b’: 2}

r = requests.post(“http://127.0.0.1:5000/add”, json=json_data)

print(r.headers)
print(r.text)


运行`client.py`,将显示:



{‘Content-Type’: ‘application/json’, ‘Content-Length’: ‘10’, ‘Server’: ‘Werkzeug/0.14.1 Python/3.6.4’, ‘Date’: ‘Sat, 07 Jul 2018 05:23:00 GMT’}
{“sum”: 3}


上面第一段内容是服务器的响应头,第二段内容是响应体,也就是服务器返回的JSON格式数据。


另外,如果需要服务器的HTTP响应头具有更好的可定制性,比如自定义`Server`,可以如下修改`add()`函数:



@app.route(‘/add’, methods=[‘POST’])
def add():
result = {‘sum’: request.json[‘a’] + request.json[‘b’]}
resp = Response(json.dumps(result), mimetype=‘application/json’)
resp.headers.add(‘Server’, ‘python flask’)
return resp


`client2.py`运行后会输出:



{‘Content-Type’: ‘application/json’, ‘Content-Length’: ‘10’, ‘Server’: ‘python flask’, ‘Date’: ‘Sat, 07 Jul 2018 05:26:40 GMT’}
{“sum”: 3}


#### 6.4 响应JSON-方案2


使用 jsonify 工具函数即可。



from flask import Flask, request, jsonify

app = Flask(“my-app”)

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

@app.route(‘/add’, methods=[‘POST’])
def add():
result = {‘sum’: request.json[‘a’] + request.json[‘b’]}
return jsonify(result)

if name == ‘main’:
app.run(host=‘127.0.0.1’, port=5000, debug=True)


#### 6.5 本节源码


[https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-004](https://bbs.csdn.net/topics/618317507)


### 7. 上传文件


上传文件,一般也是用POST方法。


#### 7.1 建立Flask项目


按照以下命令建立Flask项目HelloWorld:



mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py


#### 7.2 上传文件


这一部分的代码参考自[How to upload a file to the server in Flask](https://bbs.csdn.net/topics/618317507)。


我们以上传图片为例:  
 假设将上传的图片只允许’png’、’jpg’、’jpeg’、’gif’这四种格式,通过url`/upload`使用POST上传,上传的图片存放在服务器端的`static/uploads`目录下。


首先在项目`HelloWorld`中创建目录`static/uploads`:



mkdir HelloWorld/static/uploads


`werkzeug`库可以判断文件名是否安全,例如防止文件名是`../../../a.png`,安装这个库:



$ sudo pip3 install werkzeug


`server.py`代码:



from flask import Flask, request

from werkzeug.utils import secure_filename
import os

app = Flask(name)

文件上传目录

app.config[‘UPLOAD_FOLDER’] = ‘static/uploads/’

支持的文件格式

app.config[‘ALLOWED_EXTENSIONS’] = {‘png’, ‘jpg’, ‘jpeg’, ‘gif’} # 集合类型

判断文件名是否是我们支持的格式

def allowed_file(filename):
return ‘.’ in filename and
filename.rsplit(‘.’, 1)[1] in app.config[‘ALLOWED_EXTENSIONS’]

@app.route(‘/’)
def hello_world():
return ‘hello world’

@app.route(‘/upload’, methods=[‘POST’])
def upload():
upload_file = request.files[‘image’]
if upload_file and allowed_file(upload_file.filename):
filename = secure_filename(upload_file.filename)
# 将文件保存到 static/uploads 目录,文件名同上传时使用的文件名
upload_file.save(os.path.join(app.root_path, app.config[‘UPLOAD_FOLDER’], filename))
return ‘info is ‘+request.form.get(‘info’, ‘’)+’. success’
else:
return ‘failed’

if name == ‘main’:
app.run(port=5000, debug=True)


`app.config`中的config是字典的子类,可以用来设置自有的配置信息,也可以设置自己的配置信息。函数`allowed_file(filename)`用来判断`filename`是否有后缀以及后缀是否在`app.config['ALLOWED_EXTENSIONS']`中。


客户端上传的图片必须以`image01`标识。`upload_file`是上传文件对应的对象。`app.root_path`获取`server.py`所在目录在文件系统中的绝对路径。`upload_file.save(path)`用来将`upload_file`保存在服务器的文件系统中,参数最好是绝对路径,否则会报错(网上很多代码都是使用相对路径,但是笔者在使用相对路径时总是报错,说找不到路径)。函数`os.path.join()`用来将使用合适的路径分隔符将路径组合起来。


好了,定制客户端`client.py`:



import requests

file_data = {‘image’: open(‘Lenna.jpg’, ‘rb’)}

user_info = {‘info’: ‘Lenna’}

r = requests.post(“http://127.0.0.1:5000/upload”, data=user_info, files=file_data)

print(r.text)


运行`client.py`,当前目录下的`Lenna.jpg`将上传到服务器。


然后,我们可以在`static/uploads`中看到文件`Lenna.jpg`。


要控制上产文件的大小,可以设置请求实体的大小,例如:



app.config[‘MAX_CONTENT_LENGTH’] = 16 * 1024 * 1024 #16MB


不过,在处理上传文件时候,需要使用`try:...except:...`。


如果要获取上传文件的内容可以:



file_content = request.files[‘image’].stream.read()


#### 7.3 本节源码


[https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-005](https://bbs.csdn.net/topics/618317507)


### 8. Restful URL


简单来说,Restful URL可以看做是对 URL 参数的替代。


#### 8.1 建立Flask项目


按照以下命令建立Flask项目HelloWorld:



mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py


#### 8.2 编写代码


编辑server.py:



from flask import Flask

app = Flask(name)

@app.route(‘/’)
def hello_world():
return ‘hello world’

@app.route(‘/user/’)
def user(username):
print(username)
print(type(username))
return 'hello ’ + username

@app.route(‘/user//friends’)
def user_friends(username):
print(username)
print(type(username))
return 'hello ’ + username

if name == ‘main’:
app.run(port=5000, debug=True)


运行`HelloWorld/server.py`。使用浏览器访问`http://127.0.0.1:5000/user/letian`,HelloWorld/server.py将输出:



letian
<class ‘str’>


而访问`http://127.0.0.1:5000/user/letian/`,响应为404 Not Found。


浏览器访问`http://127.0.0.1:5000/user/letian/friends`,可以看到:



Hello letian. They are your friends.


`HelloWorld/server.py`输出:



letian
<class ‘str’>


#### 8.3 转换类型


由上面的示例可以看出,使用 Restful URL 得到的变量默认为str对象。如果我们需要通过分页显示查询结果,那么需要在url中有数字来指定页数。按照上面方法,可以在获取str类型页数变量后,将其转换为int类型。不过,还有更方便的方法,就是用flask内置的转换机制,即在route中指定该如何转换。


新的服务器代码:



from flask import Flask

app = Flask(name)

@app.route(‘/’)
def hello_world():
return ‘hello world’

@app.route(‘/page/int:num’)
def page(num):
print(num)
print(type(num))
return ‘hello world’

if name == ‘main’:
app.run(port=5000, debug=True)


[`@app.route](mailto:%60@app.route "`@app.route  ")(‘/page/int:num‘)`会将num变量自动转换成int类型。


运行上面的程序,在浏览器中访问`http://127.0.0.1:5000/page/1`,HelloWorld/server.py将输出如下内容:



1
<class ‘int’>


如果访问的是`http://127.0.0.1:5000/page/asd`,我们会得到404响应。


在官方资料中,说是有3个默认的转换器:



int accepts integers
float like int but for floating point values
path like the default but also accepts slashes


看起来够用了。


#### 8.4 一个有趣的用法


如下编写服务器代码:



from flask import Flask

app = Flask(name)

@app.route(‘/’)
def hello_world():
return ‘hello world’

@app.route(‘/page/int:num1-int:num2’)
def page(num1, num2):
print(num1)
print(num2)
return ‘hello world’

if name == ‘main’:
app.run(port=5000, debug=True)


在浏览器中访问`http://127.0.0.1:5000/page/11-22`,`HelloWorld/server.py`会输出:



11
22


#### 8.5 编写转换器


自定义的转换器是一个继承`werkzeug.routing.BaseConverter`的类,修改`to_python`和`to_url`方法即可。`to_python`方法用于将url中的变量转换后供被[`@app.route](mailto:%60@app.route "`@app.route  ")`包装的函数使用,`to\_url`方法用于`flask.url\_for`中的参数转换。


下面是一个示例,将`HelloWorld/server.py`修改如下:



from flask import Flask, url_for

from werkzeug.routing import BaseConverter

class MyIntConverter(BaseConverter):

def __init__(self, url_map):
    super(MyIntConverter, self).__init__(url_map)

def to_python(self, value):
    return int(value)

def to_url(self, value):
    return value * 2

app = Flask(name)
app.url_map.converters[‘my_int’] = MyIntConverter

@app.route(‘/’)
def hello_world():
return ‘hello world’

@app.route(‘/page/<my_int:num>’)
def page(num):
print(num)
print(url_for(‘page’, num=123)) # page 对应的是 page函数 ,num 对应对应/page/<my_int:num>中的num,必须是str
return ‘hello world’

if name == ‘main’:
app.run(port=5000, debug=True)


浏览器访问`http://127.0.0.1:5000/page/123`后,`HelloWorld/server.py`的输出信息是:



123
/page/123123


#### 8.6 本节源码


[https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-006](https://bbs.csdn.net/topics/618317507)


#### 8.7 值得读


[理解RESTful架构](https://bbs.csdn.net/topics/618317507)。


### 9. 使用`url_for`生成链接


工具函数`url_for`可以让你以软编码的形式生成url,提供开发效率。


#### 9.1 建立Flask项目


按照以下命令建立Flask项目HelloWorld:



mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py


#### 9.2 编写代码


编辑`HelloWorld/server.py`:



from flask import Flask, url_for

app = Flask(name)

@app.route(‘/’)
def hello_world():
pass

@app.route(‘/user/’)
def user(name):
pass

@app.route(‘/page/int:num’)
def page(num):
pass

@app.route(‘/test’)
def test():
print(url_for(‘hello_world’))
print(url_for(‘user’, name=‘letian’))
print(url_for(‘page’, num=1, q=‘hadoop mapreduce 10%3’))
print(url_for(‘static’, filename=‘uploads/01.jpg’))
return ‘Hello’

if name == ‘main’:
app.run(debug=True)


运行`HelloWorld/server.py`。然后在浏览器中访问`http://127.0.0.1:5000/test`,`HelloWorld/server.py`将输出以下信息:



/
/user/letian
/page/1?q=hadoop+mapreduce+10%253
/static/uploads/01.jpg


#### 9.3 本节源码


[https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-007](https://bbs.csdn.net/topics/618317507)


### 10. 使用redirect重定向网址


`redirect`函数用于重定向,实现机制很简单,就是向客户端(浏览器)发送一个重定向的HTTP报文,浏览器会去访问报文中指定的url。


#### 10.1 建立Flask项目


按照以下命令建立Flask项目HelloWorld:



mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py


#### 10.2 编写代码


使用`redirect`时,给它一个字符串类型的参数就行了。


编辑`HelloWorld/server.py`:



from flask import Flask, url_for, redirect

app = Flask(name)

@app.route(‘/’)
def hello_world():
return ‘hello world’

@app.route(‘/test1’)
def test1():
print(‘this is test1’)
return redirect(url_for(‘test2’))

@app.route(‘/test2’)
def test2():
print(‘this is test2’)
return ‘this is test2’

if name == ‘main’:
app.run(debug=True)


运行`HelloWorld/server.py`,在浏览器中访问`http://127.0.0.1:5000/test1`,浏览器的url会变成`http://127.0.0.1:5000/test2`,并显示:



this is test2


#### 10.3 本节源码


[https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-008](https://bbs.csdn.net/topics/618317507)


### 11. 使用Jinja2模板引擎


模板引擎负责MVC中的V(view,视图)这一部分。Flask默认使用Jinja2模板引擎。


Flask与模板相关的函数有:


* flask.render\_template(template\_name\_or\_list, \*\*context)  
 Renders a template from the template folder with the given context.
* flask.render\_template\_string(source, \*\*context)  
 Renders a template from the given template source string with the given context.
* flask.get\_template\_attribute(template\_name, attribute)  
 Loads a macro (or variable) a template exports. This can be used to invoke a macro from within Python code.


这其中常用的就是前两个函数。


这个实例中使用了模板继承、if判断、for循环。


#### 11.1 建立Flask项目


按照以下命令建立Flask项目HelloWorld:



mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py


#### 11.2 创建并编辑HelloWorld/templates/default.html


内容如下:



{% if page_title %} {​{ page_title }} {% endif %} {% block body %}{% endblock %}

可以看到,在``标签中使用了if判断,如果给模板传递了`page_title`变量,显示之,否则,不显示。

``标签中定义了一个名为`body`的block,用来被其他模板文件继承。

### 11.3 创建并编辑HelloWorld/templates/user_info.html
内容如下:

{% extends “default.html” %}

{% block body %}
{% for key in user_info %}

    {{ key }}: {{ user_info[key] }} 


{% endfor %}

{% endblock %}


变量`user_info`应该是一个字典,for循环用来循环输出键值对。


#### 11.4 编辑HelloWorld/server.py


内容如下:



from flask import Flask, render_template

app = Flask(name)

@app.route(‘/’)
def hello_world():
return ‘hello world’

@app.route(‘/user’)
def user():
user_info = {
‘name’: ‘letian’,
‘email’: ‘123@aa.com’,
‘age’:0,
‘github’: ‘https://github.com/letiantian’
}
return render_template(‘user_info.html’, page_title=‘letian’s info’, user_info=user_info)

if name == ‘main’:
app.run(port=5000, debug=True)


`render_template()`函数的第一个参数指定模板文件,后面的参数是要传递的数据。


#### 11.5 运行与测试


运行HelloWorld/server.py:



$ python3 HelloWorld/server.py


在浏览器中访问`http://127.0.0.1:5000/user`,效果图如下:



查看网页源码:





做了那么多年开发,自学了很多门编程语言,我很明白学习资源对于学一门新语言的重要性,这些年也收藏了不少的Python干货,对我来说这些东西确实已经用不到了,但对于准备自学Python的人来说,或许它就是一个宝藏,可以给你省去很多的时间和精力。



别在网上瞎学了,我最近也做了一些资源的更新,只要你是我的粉丝,这期福利你都可拿走。

我先来介绍一下这些东西怎么用,文末抱走。

* * *



**(1)Python所有方向的学习路线(新版)**

这是我花了几天的时间去把Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。



最近我才对这些路线做了一下新的更新,知识体系更全面了。



![在这里插入图片描述](https://img-blog.csdnimg.cn/8fc093dcfa1f476694c574db1242c05b.png)



**(2)Python学习视频**



包含了Python入门、爬虫、数据分析和web开发的学习视频,总共100多个,虽然没有那么全面,但是对于入门来说是没问题的,学完这些之后,你可以按照我上面的学习路线去网上找其他的知识资源进行进阶。



![在这里插入图片描述](https://img-blog.csdnimg.cn/d66e3ad5592f4cdcb197de0dc0438ec5.png#pic_center)



**(3)100多个练手项目**

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了,只是里面的项目比较多,水平也是参差不齐,大家可以挑自己能做的项目去练练。



![在这里插入图片描述](https://img-blog.csdnimg.cn/f5aeb4050ab547cf90b1a028d1aacb1d.png#pic_center)



**(4)200多本电子书**  

  

这些年我也收藏了很多电子书,大概200多本,有时候带实体书不方便的话,我就会去打开电子书看看,书籍可不一定比视频教程差,尤其是权威的技术书籍。



基本上主流的和经典的都有,这里我就不放图了,版权问题,个人看看是没有问题的。



**(5)Python知识点汇总**

知识点汇总有点像学习路线,但与学习路线不同的点就在于,知识点汇总更为细致,里面包含了对具体知识点的简单说明,而我们的学习路线则更为抽象和简单,只是为了方便大家只是某个领域你应该学习哪些技术栈。



![在这里插入图片描述](https://img-blog.csdnimg.cn/c741a91b05a542ba9dc8abf2f2f4b1af.png)



**(6)其他资料**



还有其他的一些东西,比如说我自己出的Python入门图文类教程,没有电脑的时候用手机也可以学习知识,学会了理论之后再去敲代码实践验证,还有Python中文版的库资料、MySQL和HTML标签大全等等,这些都是可以送给粉丝们的东西。



![在这里插入图片描述](https://img-blog.csdnimg.cn/9fa77af248b84885a6ec779b2ead064d.png)

**这些都不是什么非常值钱的东西,但对于没有资源或者资源不是很好的学习者来说确实很不错,你要是用得到的话都可以直接抱走,关注过我的人都知道,这些都是可以拿到的。**




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里无偿获取](https://bbs.csdn.net/topics/618317507)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值