table of Contents
- Yourself achieve a simple version of the web framework
- Wsgiref implement server-based module
- Dynamic static pages - Split template file
- Achieve return time - interpolation idea (dynamic page)
- Jinja2 modules use dynamic pages
- Derivation processes and small summary
- python framework for analysis and comparison of the three major Web
- Download and install the basic use Django
Yourself achieve a simple version of the web framework
Before looking at the three python web framework, we achieved a first-yourself.
Remarks:
This section focuses on the realization of ideas to master, the code is not the point
Code, there are many details have not been considered, focusing on the realization of ideas
Hand line and a web server
We generally use the browser as a client, and then based on the HTTP protocol to write server-side code as a server
First have to go look at the HTTP protocol knowledge of this together
import socket
server = socket.socket() # 基于socket通信(TCP)
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
conn, addr = server.accept()
data = conn.recv(2048) # 接收请求
print(str(data, encoding='utf-8'))
conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # 依据HTTP协议,发送响应给客户端(浏览器),这里是响应首行 + 响应头 + 空行
# response = bytes('<h3>这是响应内容</h3>', encoding='GBK')
response = '<h3>这是响应内容</h3>'.encode('GBK') # 我电脑上是GBK编码,所以使用GBK编码将字符串转成二进制
conn.send(response) # 继续发送响应体
conn.close() # 断开连接(无状态、无连接)
# 浏览器发过来的数据如下
'''
GET / HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _qddaz=QD.w3c3g1.j2bfa7.jvp70drt; csrftoken=kJHVGICQOglLxJNiui0o0UyxNtR3cXbJPXqaUFs5FoxeezuskRO7jlQE0JNwYXJs
GET /favicon.ico HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Referer: http://127.0.0.1:8080/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _qddaz=QD.w3c3g1.j2bfa7.jvp70drt; csrftoken=kJHVGICQOglLxJNiui0o0UyxNtR3cXbJPXqaUFs5FoxeezuskRO7jlQE0JNwYXJs
'''
Right then run, access the browser 127.0.0.1:8080
to see the response data
About to start the server with page requests (when I deal with, the page will often request the network in a pending state, is not very clear reason, usually this case, restart the server directly to)
Do different response processing according to the request url
The above code has achieved a basic response to the request, how it responds differently according to different requests it?
We enter a different url, and see what the server will return
Analysis request
浏览器访问 http://127.0.0.1:8080/index
GET /index HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _qddaz=QD.w3c3g1.j2bfa7.jvp70drt; csrftoken=kJHVGICQOglLxJNiui0o0UyxNtR3cXbJPXqaUFs5FoxeezuskRO7jlQE0JNwYXJs
浏览器访问 http://127.0.0.1:8080/home
GET /home HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _qddaz=QD.w3c3g1.j2bfa7.jvp70drt; csrftoken=kJHVGICQOglLxJNiui0o0UyxNtR3cXbJPXqaUFs5FoxeezuskRO7jlQE0JNwYXJs
The first line of the original request GET followed is that we want to request information ( / index Home, / Home home)
This information is what we received ( data = conn.recv(2048)
print(str(data, encoding='utf-8'))
), Can it be taken out, be treated differently depending on the value of it?
Processing request, acquires url
data = '''GET /home HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _qddaz=QD.w3c3g1.j2bfa7.jvp70drt; csrftoken=kJHVGICQOglLxJNiui0o0UyxNtR3cXbJPXqaUFs5FoxeezuskRO7jlQE0JNwYXJs'''
print(data.split('\n')[0].split(' ')[1]) # ... ---> GET /home HTTP/1.1 --> ['GET', '/home', 'HTTP/1.1'] --> /home
# /home
Based on the above cut rules, we come to different requests to different responses
import socket
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
conn, addr = server.accept()
data = conn.recv(2048).decode('utf-8')
data = data.split('\n')[0].split(' ')[1]
print(data)
conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
if data == '/index':
response = '<h3>这里是 index...</h3>'.encode('GBK')
elif data == '/home':
response = '<h3>这里是 home...</h3>'.encode('GBK')
else:
response = '<h3>404 NOT FOUND...\n找不到您要找的资源...</h3>'.encode('GBK')
conn.send(response)
conn.close()
# --- 浏览器请求 http://127.0.0.1:8080/index 的打印信息
# /index
# /favicon.ico
# --- 浏览器请求 http://127.0.0.1:8080/home 的打印信息
# /home
# /favicon.ico
# --- 浏览器请求 http://127.0.0.1:8080/de2332f 的打印信息
# /de2332f
# /favicon.ico
Success page displays different information
http://127.0.0.1:8080/index
http://127.0.0.1:8080/home
http://127.0.0.1:8080/de2332f
404 pages should also be counted as part of the design of the site, you can give a different feeling
Wsgiref implement server-based module
Front and processing scoket http pile of code is usually the same, and the business logic does not matter, if each project must write it again, it would mean a lot of trouble? Well then packaged into modules ~
However, this operation has already been done to help us, and the more powerful package, the module is wsgiref
Wsgiref with the module to do two things
- When the request, automatically parse HTTP data, and packaged into a dictionary, to facilitate the request data sent over the operation
- Before any response, automatically packaged into a data format to help meet the HTTP protocol (response data format, do not need to manually write
conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
a), returned to the server
from wsgiref.simple_server import make_server # 导模块
def run(env, response):
"""
先不管这里的 env 和 response 什么个情况
env:是请求相关的数据,wsgiref帮我们把请求包装成了一个大字典,方便取值
response:是响应相关的数据
"""
response('200 OK', [])
print(env)
current_path = env.get('PATH_INFO')
print(current_path)
if current_path == '/index':
return ['hello, there is index...'.encode('utf-8')]
elif current_path == '/login':
return ['hello, there is login...'.encode('utf-8')]
else:
return ['sorry... that pages you want is not found...'.encode('utf-8')]
if __name__ == '__main__':
# 实时监测 127.0.0.1:8080 地址,一旦有客户端连接,会自动加括号调用 run 方法
server = make_server('127.0.0.1', 8080, run)
server.serve_forever() # 启动服务器
# /index
# ---> env 的数据(手动删减了一些),可以看到其中有个 PATH_INFO 是我们要的东西(还有浏览器版本啊,USER-AGENT啊,客户端系统环境变量啊之类的信息)
'''{'ALLUSERSPROFILE': 'C:\\ProgramData', ...省略部分... , 'COMSPEC': 'C:\\Windows\\system32\\cmd.exe', 'PROCESSOR_IDENTIFIER': 'Intel64 Family 6 Model 60 Stepping 3, GenuineIntel', 'PROCESSOR_LEVEL': '6', 'PROCESSOR_REVISION': '3c03', 'PYTHONIOENCODING': 'UTF-8', 'SESSIONNAME': 'Console', 'SYSTEMDRIVE': 'C:', 'SERVER_PORT': '8080', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/index', 'QUERY_STRING': '', 'REMOTE_ADDR': '127.0.0.1', 'CONTENT_TYPE': 'text/plain', 'HTTP_HOST': '127.0.0.1:8080', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3', csrftoken=kJHVGICQOglLxJNiui0o0UyxNtR3cXbJPXqaUFs5FoxeezuskRO7jlQE0JNwYXJs', mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), }'''
Foreshadowing
Split server code
Server-side code, routing configuration, view functions, according to the current redundant writing all together, when the late extensions, this document will become very long, inconvenient to maintain, so he chose to split open
The server code is split into three parts as follows:
server.py put the server code
Routing and put urls.py view function correspondence relationship
views.py put view function / type (business logic)
views.py
def index(env):
return 'index'
def login(env):
return 'login'
urls.py
from views import *
urls = [
('/index', index),
('/login', login),
]
server.py
from wsgiref.simple_server import make_server # 导模块
from urls import urls # 引入 urls.py 里的 urls列表(命名的不是很规范)
def run(env, response):
response('200 OK', [])
current_path = env.get('PATH_INFO')
func = None
for url in urls:
if current_path == url[0]:
func = url[1]
break
if func:
res = func(env)
else:
res = '404 Not Found.'
return [res.encode('utf-8')] # 注意这里返回的是一个列表(可迭代对象才行),wsgiref 模块规定的,可能还有其他的用途吧
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run)
server.serve_forever()
Support new request address (add new pages / new features)
After the split of the above, the subsequent want to support other url, just add a correspondence relationship urls.py in the function implemented in the views.py in, restart the server to access
To support http://127.0.0.1:8080/new_url
access to, for example
urls.py
from views import *
urls = [
('/index', index),
('/login', login),
('/new_url', new_url),
]
views.py
def index(env):
return 'index'
def login(env):
return 'login'
def new_url(env):
# 这里可以写一堆逻辑代码
return 'new_url'
Restart the server , open the browser, the webhttp://127.0.0.1:8080/new_url
Extensibility a lot higher, and the logic clearer, less likely to mistake (benefit framework of withdrawals, why not write out the reasons for the framework of this piece of code written in too little, not used to, and not a framework write to)
Dynamic static pages - Split template file
Written in front of so many, just plain text information has been returned, but we generally return the requested page is a good browser rendering ornate page, then put back to how gorgeous pages?
Well the page is HTML + CSS + JS rendered, so we can put HTML files as data on the body in response to a direct return back
Create a step function or refresher
- And adding a route in view of the correspondence between a function inside urls.py
- In views.py inside with the view function, and write the internal logic code
- Restart the server, open the browser page views
Return to static pages - Case
Here then we will go above new_url write, use it to return to a Web page
Create a new templates folder, designed to put HTML files
templates/new_url.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>New URL</h1>
<h5>Wellcome!</h5>
</body>
</html>
views.py
def index(env):
return 'index'
def login(env):
return 'login'
def new_url(env):
# 读取并把 new_url 文件返回给客户端(浏览器)
with open(r'templates/new_url.html', 'rb') as f:
html_data = f.read()
return html_data.decode('utf-8') # 因为 run 函数那里做了 encode, 而二进制数据没有 encode这个方法,所以这里先解码一下,然后那边再编码一下
Restart the server, accessed using a browser
The above mentioned static pages, then what is a static page? What is the dynamic pages?
Static pages: pure html pages, data is written dead, all get the same url request data are the same
Dynamic pages: the back-end data registration, data is not written dead, is dynamic stitching, such as:
Get the current real-time back-end "pass" (plug) to show the front page
Back-end data acquisition "transfer" from the database to the front page display
Achieve return time - interpolation idea (dynamic page)
How to insert it in html in time?
Html where to insert? That seems to be replacing achieve ah?
html_data = f.read()
? Html seems to be read out, but also binary, binary can decode become strings, strings there are ways to replace the replacement string, I just write about the content of the page, and then replace the time?
Zou good first base ho
templates / get_time.html write Display page
put_times_here used to do a placeholder for a while to give him time to replace
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>北京时间:</h1>
<h1>put_time_here</h1>
</body>
</html>
urls.py routing and view function correspondence relationship
from views import *
urls = [
('/index', index),
('/login', login),
('/new_url', new_url),
('/get_time', get_time),
]
views.py achieve view function
def index(env):
return 'index'
def login(env):
return 'login'
def new_url(env):
# 读取并把 new_url 文件返回给客户端(浏览器)
with open(r'templates/new_url.html', 'rb') as f:
html_data = f.read()
return html_data
def get_time(env):
# 读取并把 get_time 文件返回给客户端(浏览器)
with open(r'templates/get_time.html', 'rb') as f:
html_data = f.read().decode('utf-8')
import time
html_data = html_data.replace('put_time_here', time.strftime("%Y-%m-%d %X"))
return html_data
Reboot the server and open a browser to access http://127.0.0.1:8080/get_time
The key ideas: the equivalent of a placeholder, string replacement, front-end format to replace the late character of unified regulations, the easy to read and unified treatment, which in fact is the current template syntax prototype
We just need to deal with a good string (HTML format) returned to the browser until the browser page rendering can have the effect of
Jinja2 modules use dynamic pages
jinja2 module has a set of template syntax, I can help make it easier to write code in html (I wanted to write the same code-behind), so that the tip can also use some of the syntax operation trailing edges of the incoming data
Installation jinja2
jinja2 not a python interpreter comes, so we need to install their own
Since jinja2 flask is dependent on the frame, the frame also carrying the flask download module installed jinja2
Command line, pip3 install jinja2
or a graphical user mounting (refer to Django installation method)
Preliminary use
Here are just know that there is such a thing template syntax allows us to easily write some html stuff like variables, and does not speak of grammar jinja2, there will be follow-up
Cases - shows dictionary information
urls.py
from views import *
urls = [
('/index', index),
('/login', login),
('/new_url', new_url),
('/get_time', get_time),
('/show_dic', show_dic),
]
views.py
def index(env):
return 'index'
def login(env):
return 'login'
def new_url(env):
# 读取并把 new_url 文件返回给客户端(浏览器)
with open(r'templates/new_url.html', 'rb') as f:
html_data = f.read()
return html_data
def get_time(env):
# 读取并把 get_time 文件返回给客户端(浏览器)
with open(r'templates/get_time.html', 'rb') as f:
html_data = f.read().decode('utf-8')
import time
html_data = html_data.replace('put_time_here', time.strftime("%Y-%m-%d %X"))
return html_data
def show_dic(env):
user = {
"username": "jason",
"age": 18,
}
with open(r'templates/show_dic.html', 'rb') as f:
html_data = f.read()
# 使用 jinja2 的模板语法来将数据渲染到页面上(替换占位符)
from jinja2 import Template
tmp = Template(html_data)
res = tmp.render(dic=user) # 将字典 user 传递给前端页面,前端页面通过变量名 dic 就能够获取到该字典
return res
templates / show_dic.html write page
jinja2 to extend the dictionary dot syntax support ( {{ dic.username }}
)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Nice to meet you~ i'm {{ dic.username }} , and i'm {{ dic.age }} years old.</h1>
<p>username: {{ dic['username']}}</p>
<p>age: {{ dic.get('age')}}</p>
</body>
</html>
Reboot the server and open a browser to access http://127.0.0.1:8080/show_dic
Why dynamic?
If you change the dictionary's value, then requested this page, the data displayed will also change (note that this dictionary are generally acquired elsewhere over)
模板语法(贴近python语法): 前端也能够使用后端的一些语法操作后端传入的数据
{{data.password}} # jinja2 多给字典做了 点语法支持
... 其他的语法,写法
for 循环
{%for user_dict in user_list%}
<tr>
<td>{{user_dict.id}}</td>
<td>{{user_dict.name}}</td>
<td>{{user_dict.password}}</td>
</tr>
{%endfor%}
Advanced Case - rendering database data to the page
Thinking
pymsql 从数据库取数据(指定成 列表套字典 的格式(DictCursor))
后台 python 代码处理数据
交由 jinja2 模块语法渲染到 html 页面上
数据条数不定怎么办?
有多少条记录就显示多少条呗...循环?
表格格式先写好,然后循环渲染数据到标签上(特定语法表示循环)
data preparation
Create a database django_test_db , and then execute the following SQL command
/*
Navicat MySQL Data Transfer
Source Server : localhost-E
Source Server Type : MySQL
Source Server Version : 50645
Source Host : localhost:3306
Source Schema : django_test_db
Target Server Type : MySQL
Target Server Version : 50645
File Encoding : 65001
Date: 15/09/2019 00:41:09
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user_info
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES (1, 'jason', '123');
INSERT INTO `user_info` VALUES (2, 'tank', '123');
INSERT INTO `user_info` VALUES (3, 'jerry', '123');
INSERT INTO `user_info` VALUES (4, 'egon', '456');
SET FOREIGN_KEY_CHECKS = 1;
Routing and view function with
urls.py
from views import *
urls = [
('/index', index),
('/login', login),
('/new_url', new_url),
('/get_time', get_time),
('/show_dic', show_dic),
('/get_users', get_users),
]
views.py
def index(env):
return 'index'
def login(env):
return 'login'
def new_url(env):
# 读取并把 new_url 文件返回给客户端(浏览器)
with open(r'templates/new_url.html', 'rb') as f:
html_data = f.read()
return html_data
def get_time(env):
# 读取并把 get_time 文件返回给客户端(浏览器)
with open(r'templates/get_time.html', 'rb') as f:
html_data = f.read().decode('utf-8')
import time
html_data = html_data.replace('put_time_here', time.strftime("%Y-%m-%d %X"))
return html_data
def show_dic(env):
user = {
"username": "jason",
"age": 18,
}
with open(r'templates/show_dic.html', 'rb') as f:
html_data = f.read()
# 使用 jinja2 的模板语法来将数据渲染到页面上(替换占位符)
from jinja2 import Template
tmp = Template(html_data)
res = tmp.render(dic=user) # 将字典 user 传递给前端页面,前端页面通过变量名 dic 就能够获取到该字典
return res
# 先写个空函数在这里占位置,去把 pymysql 查数据的写了再过来完善
def get_users(env):
# 从数据库取到数据
import op_mysql
user_list = op_mysql.get_users()
with open(r'templates/get_users.html', 'r', encoding='utf-8') as f:
html_data = f.read()
from jinja2 import Template # 其实这个引入应该放在页面最上方去的,但为了渐进式演示代码推进过程,就放在这里了
tmp = Template(html_data)
res = tmp.render(user_list=user_list)
return res
op_mysql.py If your configuration does not change overnight just have to be yourself
import pymysql
def get_cursor():
server = pymysql.connect(
# 根据自己电脑上 mysql 的情况配置这一块的内容
host='127.0.0.1',
port=3306,
user='root',
password='000000',
charset='utf8', # 千万注意这里是 utf8 !
database='django_test_db',
autocommit=True
)
cursor = server.cursor(pymysql.cursors.DictCursor)
return cursor
def get_users():
cursor = get_cursor() # 连接数据库
sql = "select * from user_info" # 把用户的所有信息查出来(一般不会把密码放回给前端的,这里只是为了做演示)
affect_rows = cursor.execute(sql)
user_list = cursor.fetchall()
return user_list
templates / get_users.html user information display page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 引入jquery bootstrap 文件的 CDN -->
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h2 class="text-center">用户数据展示</h2>
<table class="table table-hover table-bordered table-striped">
<thead>
<tr>
<th>id</th>
<th>username</th>
<th>password</th>
</tr>
</thead>
<tbody>
<!-- jinja2 的模版语法(for循环) -->
{%for user_dict in user_list%}
<tr>
<td>{{user_dict.id}}</td>
<td>{{user_dict.username}}</td>
<td>{{user_dict.password}}</td>
</tr>
{%endfor%}
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
Access the browser http://127.0.0.1:8080/get_users
, restart the server, switch back to your browser to see page effects
Derivation processes and small summary
1.纯手撸web框架
1.手动书写socket代码
2.手动处理http数据
2.基于wsgiref模块帮助我们处理scoket以及http数据(顶掉上面的歩鄹)
wsgiref模块
1.请求来的时候 解析http数据帮你打包成一个字典传输给你 便于你操作各项数据
2.响应走的时候 自动帮你把数据再打包成符合http协议格式的样子 再返回给前端
3.封装路由与视图函数对应关系 以及视图函数文件 网站用到的所有的html文件全部放在了templates文件夹下
1.urls.py 路由与视图函数对应关系
2.views.py 视图函数 (视图函数不单单指函数 也可以是类)
3.templates 模板文件夹
4.基于jinja2实现模板的渲染
模板的渲染
后端生成好数据 通过某种方式传递给前端页面使用(前端页面可以基于模板语法更加快捷简便使用后端传过来的数据)
flow chart
Small extension
Do not know is to encode or decode, they can use what method
Binary data corresponding to the character string must be decoded to decode it
Corresponding to the string must be encoded to encode binary data die
Data type conversion techniques (encoding process) (data + encoding)
# 转成 bytes 类型
bytes(data, encoding='utf-8')
# 转成 str 类型
str(data, encoding='utf-8')
python framework for analysis and comparison of the three major Web
Django
Large and comes with features particularly special, similar to an aircraft carrier
Cons: sometimes too heavy (less than a lot of small projects)
Flask
Dapper, in particular less own function, it is all dependent on the third-party components (modules)
Particularly large number of third-party components -> If you add up all the third-party components, can be overshadowed by django
Disadvantages: relatively limited to third-party developers (probably a bug, etc.)
Tornado
Natural non-blocking asynchronous frame, very fast, can be withstood high concurrency
Can develop a game server (but game development, or C and C ++ used more, faster execution efficiency)
Hand line and comparison of three parts in the frame
Derivation line and in front of the hand, the entire process the frame can be roughly divided into three portions
A: transmitting and receiving a processing request in response to the socket
B: Routing and view function
C: template syntax to a dynamic page rendering data
Django
A: with others of wsgiref module
B: the view from Dailu function file
C: comes with a set of template syntax
Flask
A: with others of the modules werkzeug (based wsgiref package)
B: view from the function file with Router
C: with others of jinja2
Tornado
A, B, C all have their own implementations
Download and install the basic use Django
See my other blog post: Django- download and install - Configure - Create django project - three tricks using simple