Django- hand line and simple web framework - dynamic web pages -wsgiref framework comparison mainstream acquaintance -jinja2 acquaintance -python -00

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:8080to 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

  1. When the request, automatically parse HTTP data, and packaged into a dictionary, to facilitate the request data sent over the operation
  2. 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_urlaccess 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 jinja2or 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

Guess you like

Origin www.cnblogs.com/suwanbin/p/11520959.html