Django(一)

Djangocss

web框架的本質及自定義web框架

  全部的Web應用本質上就是一個socket服務端,而用戶的瀏覽器就是一個socket客戶端,基於請求作出響應,客戶都先請求,服務端作出對應的響應,按照http協議的請求協議發送請求,服務端按照http協議的響應協議來響應請求,這樣的網絡通訊,咱們就能夠本身實現Web框架了。html

  基於socket來本身實現一個web框架,寫一個web服務端,讓瀏覽器來請求,並經過本身的服務端把頁面返回給瀏覽器,瀏覽器渲染出咱們想要的效果。  前端

 

1、簡單的web框架python

import socket

sk = socket.socket()
sk.bind(('127.0.0.1',8001))
sk.listen()

conn,addr = sk.accept()
msg = conn.recv(1024)
str_msg = msg.decode('utf-8')
print(str_msg)

conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
conn.send(b'hello world')

conn.close()
sk.close()

 在瀏覽器訪問服務端:mysql

重啓咱們的代碼,而後在網址中輸入這個:web

 瀏覽器發過來一堆的消息,咱們給瀏覽器回覆(響應)信息的時候,也要按照一個消息格式來寫,這些都是http協議規定的,那麼咱們就來學習一下http協議,而後繼續完善咱們的web框架:sql

   HTTP協議:https://www.cnblogs.com/clschao/articles/9230431.html數據庫

 2、返回Html文件的web框架:瀏覽器

首先寫一個html文件,內容以下,名稱爲index.html:服務器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <style>
        h1{
            background-color: green;
            color: white;
        }
    </style>
</head>
<body>

<h1>世界,你好!</h1>
<img src="https://img3.chouti.com/img_1557880036293.jpg?imageView2/1/q" alt="">

<script>
    alert('這是咱們第一個網頁')
</script>

</body>
</html>

  準備咱們的python代碼,服務端程序,文件內容以下,文件名稱爲   返回Html文件的web框架.py :

import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8001))
sk.listen()

conn,addr = sk.accept()
msg = conn.recv(1024)
str_msg = msg.decode('utf-8')
print('瀏覽器請求信息:',str_msg)
conn.send(b'HTTP/1.1 200 ok \r\n\r\n')

with open('index.html','rb') as f:
    data = f.read()
conn.send(data)

conn.close()
sk.close()
import socket
from threading import Thread

server = socket.socket()
server.bind(('0.0.0.0',8001))
server.listen()

def communication(conn):
    #接受請求數據
    msg = conn.recv(1024).decode('utf-8')
    print(msg)
    #組合響應協議的消息格式,而後發送響應信息
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')

    #打開index.html文件,返回給前端
    with open('index.html', 'rb') as f:  #沒有引入文件形式的html頁面
        data = f.read()
    conn.send(data)
    conn.close()

while 1:
    #接受鏈接
    conn, add = server.accept()
    #開啓線性併發
    t = Thread(target=communication,args=(conn,))
    t.start()
返回html文件(多線程,函數)web框架.py

 

頁面上輸入網址看效果:css樣式和js效果都有。

 

將index.html 文件中css樣式與js語句寫成文件,圖片網絡地址改成本地地址(01.jpg):

index.css:

h1{
    background-color: green;
    color: white;
}

index.js

alert('這是咱們第一個網頁') 

index.html改成:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="index.css">
    <!--<style>-->
        <!--h1{-->
            <!--background-color: green;-->
            <!--color: white;-->
        <!--}-->
    <!--</style>-->
</head>
<body>

<h1>世界,你好!</h1>
<img src="01.jpg" alt="">

<!--<script>-->
    <!--alert('這是咱們第一個網頁')-->
<!--</script>-->

<script src="index.js"></script>
</body>
</html>

 一樣使用咱們以前的python程序,來看效果:

  須要將html頁面須要的css、js、圖片等文件也發送給瀏覽器就,而且這些靜態文件都是瀏覽器單獨過來請求的,其實和標籤的屬性有有關係,css文件是link標籤的href屬性:<link rel="stylesheet" href="test.css">,js文件是script標籤的src屬性:<script src="test.js"></script>,圖片文件是img標籤的src屬性:<img src="meinv.png" alt="" width="100" height="100"> ,那個.ico文件是link標籤的屬性:<link rel="icon" href="wechat.ico">,其實這些屬性都會在頁面加載的時候,單獨到本身對應的屬性值裏面取請求對應的文件數據,並且咱們若是在值裏面寫的都是本身本地的路徑,那麼都會來本身的本地路徑來找,若是咱們寫的是相對路徑,就會到咱們本身的網址+文件名稱,這個路徑來找它須要的文件,因此咱們只須要將這些請求作一些響應,將對應的文件數據相應給瀏覽器就能夠了!

 3、返回靜態文件的高級web框架

   服務端程序:

import socket

sk = socket.socket()
sk.bind(('127.0.0.1',8001))
sk.listen()

while 1:
    conn,addr = sk.accept()
    msg = conn.recv(1024)
    str_msg = msg.decode('utf-8')
    path = str_msg.split('\r\n')[0].split(' ')[1]
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')

    if path == '/':
        print(msg.decode('utf-8'))
        with open('index.html','rb') as f:
            data = f.read()
        conn.send(data)
        conn.close()
    elif path == '/01.jpg':
        with open('01.jpg','rb') as f:
            pic_data = f.read()
        conn.send(pic_data)
        conn.close()
    elif path == '/index.css':
        with open('index.css','rb') as f:
            css_data = f.read()
        conn.send(css_data)
        conn.close()

    elif path == '/wechat.ico':
        with open('wechat.ico','rb') as f:
            ico_data = f.read()
        conn.send(ico_data)
        conn.close()

    elif path == '/index.js':
        with open('index.js','rb') as f:
            js_data = f.read()
        conn.send(js_data)
        conn.close()

  index.html:添加了<link rel="icon" href="wechat.ico">屬性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="index.css">
    <link rel="icon" href="wechat.ico">
    <!--<style>-->
        <!--h1{-->
            <!--background-color: green;-->
            <!--color: white;-->
        <!--}-->
    <!--</style>-->
</head>
<body>

<h1>世界,你好!</h1>
<img src="01.jpg" alt="">

<!--<script>-->
    <!--alert('這是咱們第一個網頁')-->
<!--</script>-->

<script src="index.js"></script>
</body>
</html>

import socket
from threading import Thread

server = socket.socket()
server.bind(('0.0.0.0',8001))
server.listen()

def communication(conn):
    msg = conn.recv(1024).decode('utf-8')
    print(msg)
    path = msg.split('\r\n')[0].split(' ')[1]
    print(path)
    #針對不一樣的請求路徑,返回不一樣的文件
    if path =='/':
        conn.send(b'HTTP/1.1 200 ok \r\nk1:v1\r\n\r\n')
        with open('index.html', 'rb') as f:
            data = f.read()
        conn.send(data)
        conn.close()
    elif path =='/index.css':
        conn.send(b'HTTP/1.1 200 ok \r\nk1:v1\r\n\r\n')
        with open('index.css', 'rb') as f:
            data = f.read()
        conn.send(data)
        conn.close()
    elif path =='/index.js':
        conn.send(b'HTTP/1.1 200 ok \r\nk1:v1\r\n\r\n')
        with open('index.js', 'rb') as f:
            data = f.read()
        conn.send(data)
        conn.close()
    elif path =='/wechat.ico':
        conn.send(b'HTTP/1.1 200 ok \r\nk1:v1\r\n\r\n')
        with open('wechat.ico', 'rb') as f:
            data = f.read()
        conn.send(data)
        conn.close()

    elif path =='/01.jpg':
        conn.send(b'HTTP/1.1 200 ok \r\nk1:v1\r\n\r\n')
        with open('01.jpg', 'rb') as f:
            data = f.read()
        conn.send(data)
        conn.close()

while 1:
    conn, add = server.accept()
    t = Thread(target=communication,args=(conn,))
    t.start()
進階版返回靜態文件的高級web框架.py

 

四:函數多線程版返回靜態文件的web框架

靜態文件使用:index.html , index.css , index.js , 01.jpg , wechat.ico

python代碼:

import socket
from threading import Thread

server = socket.socket()
server.bind(('127.0.0.1',8001))
server.listen()

def html(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('index.html', 'rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()
def css(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('index.css','rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

def js(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('index.js', 'rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

def ico(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('wechat.ico','rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()
def jpg(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('01.jpg', 'rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

urlpatterns = [
    ('/',html),
    ('/index.css',css),
    ('/index.js',js),
    ('/wechat.ico',ico),
    ('/01.jpg',jpg),
]


def communication(conn):
    msg = conn.recv(1024).decode('utf-8')
    print(msg)
    path = msg.split('\r\n')[0].split(' ')[1]
    print(path)
    #針對不一樣的請求路徑,返回不一樣的文件
    for urlpattern in urlpatterns:
        if urlpattern[0] == path:
            # urlpattern[1](conn)
            # 多線程執行函數
            t = Thread(target=urlpattern[1],args=(conn,))
            t.start()

    # if path =='/':
    #     html(conn)
    # elif path =='/index.css':
    #     css(conn)
    # elif path =='/index.js':
    #     js(conn)
    # elif path =='/wechat.ico':
    #     ico(conn)
    # elif path =='/01.jpg':
    #     jpg(conn)

while 1:
    conn, add = server.accept()
    t = Thread(target=communication,args=(conn,))
    t.start()

5、返回不一樣html頁面的web框架

靜態文件使用:index.html , index.css , index.js , 01.jpg , wechat.ico

添加返回的頁面 home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>首頁</h1>
<h1>time</h1>

</body>
</html>

 

python代碼:

import socket
from threading import Thread

server = socket.socket()
server.bind(('0.0.0.0',8001))
server.listen()

def html(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('index.html', 'rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()
def css(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('index.css', 'rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

def js(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('index.js', 'rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

def ico(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('wechat.ico', 'rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()
def jpg(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('01.jpg', 'rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

def home(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('home.html', 'rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

urlpatterns = [
    ('/',html),
    ('/index.css',css),
    ('/index.js',js),
    ('/wechat.ico',ico),
    ('/01.jpg',jpg),
    ('/home.html',home),
]


def communication(conn):
    msg = conn.recv(1024).decode('utf-8')
    # print(msg)
    path = msg.split('\r\n')[0].split(' ')[1]

    #針對不一樣的請求路徑,返回不一樣的文件
    for urlpattern in urlpatterns:
        # print(path)
        if urlpattern[0] == path:
            # urlpattern[1](conn)
            # 多線程執行函數
            t = Thread(target=urlpattern[1],args=(conn,))
            t.start()

while 1:
    conn, add = server.accept()
    t = Thread(target=communication,args=(conn,))
    t.start()

 

 

6、返回動態l頁面的web框架

靜態文件使用:index.html , index.css , index.js , 01.jpg , wechat.ico ,home.html

python 代碼:

import time
import socket
from threading import Thread

server = socket.socket()
server.bind(('0.0.0.0',8001))
server.listen()

def html(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('index.html','rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

def css(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('index.css','rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

def js(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('index.js','rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

def ico(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('wechat.ico','rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

def jpg(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    with open('01.jpg', 'rb') as f:
        data = f.read()
    conn.send(data)
    conn.close()

def home(conn):
    conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
    current_time = str(time.time())
    with open('home.html','r',encoding='utf-8') as f:
        data = f.read()
        data = data.replace('time',current_time)
    conn.send(data.encode('utf-8'))
    conn.close()

urlpatterns = [
    ('/',html),
    ('/index.css',css),
    ('/index.js',js),
    ('/favicon.ico',ico),
    ('/01.jpg',jpg),
    ('/home.html',home),
]

def communication(conn):
    msg = conn.recv(1024).decode('utf-8')
    # print(msg)
    path = msg.split('\r\n')[0].split(' ')[1]

    #針對不一樣的請求路徑,返回不一樣的文件
    for urlpattern in urlpatterns:
        # print(path)
        if urlpattern[0] == path:
            # urlpattern[1](conn)
            # 多線程執行函數
            t = Thread(target=urlpattern[1],args=(conn,))
            t.start()

while 1:
    conn, add = server.accept()
    t = Thread(target=communication,args=(conn,))
    t.start()

 

 

7、wsgiref模塊版web框架

   wsgiref模塊實際上是將整個請求信息給封裝了起來,不須要你本身處理了,假如它將全部請求信息封裝成了一個叫作request的對象,那麼你直接request.path就能獲取到用戶此次請求的路徑,request.method就能獲取到本次用戶請求的請求方式(get仍是post)等,那這個模塊用起來,咱們再寫web框架就簡單了不少。

   對於真實開發中的python web程序來講,通常會分爲兩部分:服務器程序和應用程序。

   服務器程序負責對socket服務器進行封裝,並在請求到來時,對請求的各類數據進行整理。

   應用程序負責具體的邏輯處理。爲了方便應用程序的開發,就出現了衆多的Web框架,例如:Django、Flask、web.py 等。不一樣的框架有不一樣的開發方式,可是不管如何,開發出的應用程序都要和服務器程序配合,才能爲用戶提供服務。

   這樣,服務器程序就須要爲不一樣的框架提供不一樣的支持。這樣混亂的局面不管對於服務器仍是框架,都是很差的。對服務器來講,須要支持各類不一樣框架,對框架來講,只有支持它的服務器才能被開發出的應用使用。最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。若是要動態生成HTML,就須要把上述步驟本身來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,若是咱們本身來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。

          正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口協議來實現這樣的服務器軟件,讓咱們專心用Python編寫Web業務。

   這時候,標準化就變得尤其重要。咱們能夠設立一個標準,只要服務器程序支持這個標準,框架也支持這個標準,那麼他們就能夠配合使用。一旦標準肯定,雙方各自實現。這樣,服務器能夠支持更多支持標準的框架,框架也可使用更多支持標準的服務器。

   WSGI(Web Server Gateway Interface)就是一種規範,它定義了使用Python編寫的web應用程序與web服務器程序之間的接口格式,實現web應用程序與web服務器程序間的解耦。

   經常使用的WSGI服務器有uwsgi、Gunicorn。而Python標準庫提供的獨立WSGI服務器叫wsgiref,Django開發環境用的就是這個模塊來作服務器。

from wsgiref.simple_server import make_server
# wsgiref自己就是個web框架,提供了一些固定的功能(請求和響應信息的封裝,不須要咱們本身寫原生的socket了也不須要我們本身來完成請求信息的提取了,提取起來很方便)
#函數名字隨便起
def application(environ, start_response):
    '''
    :param environ: 是所有加工好的請求信息,加工成了一個字典,經過字典取值的方式就能拿到不少你想要拿到的信息
    :param start_response: 幫你封裝響應信息的(響應行和響應頭),注意下面的參數
    :return:
    '''
    start_response('200 OK', [('Content-Type', 'text/html'),('k1','v1')])
    print(environ)
    print(environ['PATH_INFO'])  #輸入地址127.0.0.1:8000,這個打印的是'/',輸入的是127.0.0.1:8000/index,打印結果是'/index'
    return [b'<h1>Hello, web!</h1>']

httpd = make_server('127.0.0.1', 8080, application)

print('Serving HTTP on port 8080...')
# 開始監聽HTTP請求:
httpd.serve_forever()

 

 簡單wsgiref模塊版web框架:

 靜態文件使用:index.html , home.html

import time
from wsgiref.simple_server import make_server

def app(environ,start_response):
    start_response('200 OK', [('Content-Type', 'text/html'), ('k1', 'v1')])
    print(environ)
    path = environ['PATH_INFO']

    for urlpattern in urlpatterns:
        print(path)
        if urlpattern[0] == path:
            ret = urlpattern[1]()
            return ret

def html():
    with open('index.html', 'rb') as f:
        data = f.read()
    return [data]

def home():
    current_time = str(time.time())
    with open('home.html', 'r',encoding='utf-8') as f:
        data = f.read()
        data = data.replace('time',current_time).encode('utf-8')
    return [data]

urlpatterns = [
    ('/',html),
    ('/home.html',home),
]

httpd = make_server('127.0.0.1', 8001, app)
httpd.serve_forever()

 

 

一個完整的web項目,用戶登陸認證的項目,須要鏈接數據庫,在mysql數據庫裏面準備一些表和數據:

mysql> create database day53;
Query OK, 1 row affected (0.12 sec)

mysql> use day53;
Database changed
mysql> create table userinfo(id int primary key auto_increment,username char(20) not null unique,password char(20) not null);
Query OK, 0 rows affected (0.36 sec)

mysql> insert into userinfo(username,password) values('xu','123'),('wu','456');
Query OK, 2 rows affected (0.17 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from userinfo;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | xu       | 123      |
|  2 | wu       | 456      |
+----+----------+----------+
2 rows in set (0.00 sec)

python服務端代碼(主邏輯代碼):

from urllib.parse import parse_qs
from wsgiref.simple_server import make_server
import webauth

def application(environ, start_response):

    start_response('200 OK', [('Content-Type', 'text/html')])
    # print(environ)
    # print(environ['PATH_INFO'])
    path = environ['PATH_INFO']
    # 用戶獲取login頁面的請求路徑
    if path == '/login':
        with open('login.html','rb') as f:
            data = f.read()
    # 針對form表單提交的auth路徑,進行對應的邏輯處理
    elif path == '/auth/':
        #登錄認證
        #1.獲取用戶輸入的用戶名和密碼

        #2.去數據庫作數據的校驗,查看用戶提交的是否合法
        # user_information = environ['']
        if environ.get("REQUEST_METHOD") == "POST":
            # 獲取請求體數據的長度,由於提交過來的數據須要用它來提取,注意POST請求和GET請求的獲取數據的方式不一樣
            try:
                request_body_size = int(environ.get('CONTENT_LENGTH', 0))
            except (ValueError):
                request_body_size = 0
            # POST請求獲取數據的方式
            request_data = environ['wsgi.input'].read(request_body_size)
            print('>>>>>',request_data) # >>>>> b'username=chao&password=123',是個bytes類型數據
            print('?????',environ['QUERY_STRING'])#????? 空的,由於post請求只能按照上面這種方式取數據
            # parse_qs能夠幫咱們解析數據
            re_data = parse_qs(request_data.decode('utf-8')) #將bytes類型數據轉碼
            print('拆解後的數據',re_data)  #拆解後的數據 {'username': ['wu'], 'password': ['456']}
            username = re_data['username'][0]
            password = re_data['password'][0]
            print(username,password)
            # 進行驗證
            status = webauth.auth(username,password)
            if status:
                # 3.將相應內容返回
                with open('success.html','rb') as f:
                    data = f.read()
            else:
                data = b'auth error'

        if environ.get("REQUEST_METHOD") == "GET":
            # GET請求獲取數據的方式,只能按照這種方式取
            print('?????',environ['QUERY_STRING']) #????? username=xu&password=123,是個字符串類型數據
            request_data = environ['QUERY_STRING']
            print('>>>>request_data', request_data)
            # parse_qs能夠幫咱們解析數據
            re_data = parse_qs(request_data)
            print('拆解後的數據', re_data)
            username = re_data['username'][0]
            password = re_data['password'][0]
            print(username,password)
            # 進行驗證
            status = webauth.auth(username,password)
            if status:
                # 3.將相應內容返回
                with open('success.html','rb') as f:
                    data = f.read()
            else:
                data = b'auth error'
            # 不論是post仍是get請求都不能直接拿到數據,拿到的數據還須要咱們來進行分解提取,因此咱們引入urllib模塊來幫咱們分解
     
    else:
        data = b'sorry 404!,not found the page'
    return [data]

httpd = make_server('127.0.0.1', 8001, application)
print('Serving HTTP on port 8001...')
# 開始監聽HTTP請求:
httpd.serve_forever()

 

登錄頁面 login.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<!--form標籤中 method屬性能夠等於get-->
<form action="http://127.0.0.1:8001/auth/" method="post">
    用戶名<input type="text" name="username">
    密碼 <input type="password" name="password">
    <input type="submit">
</form>

</body>
</html>

 

用戶驗證 webauth.py文件:

def auth(username,password):
    import pymysql conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='123', database='day53', charset='utf8' ) print('userinfo',username,password) cursor = conn.cursor(pymysql.cursors.DictCursor) sql = 'select * from userinfo where username=%s and password=%s;' res = cursor.execute(sql, [username, password]) if res: return True else: return False

用戶登錄成功跳轉 success.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>

<h1>恭喜登錄成功!</h1>

</body>
</html>

 

一個比較low的文件配置版web框架:

 1.pycharm建立userinfo表格:

#建立表,插入數據
def createtable():
    import pymysql
    conn = pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123',
        database='day53',
        charset='utf8'
    )
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    sql = '''
        -- 建立表
        create table userinfo(id int primary key auto_increment,username char(20) not null unique,password char(20) not null);
        -- 插入數據
        insert into userinfo(username,password) values('chao','666'),('sb1','222');
    '''
    cursor.execute(sql)
    conn.commit()
    cursor.close()
    conn.close()

 

2.框架主體:

from urls import urlpatterns
from wsgiref.simple_server import make_server

#這個文件裏面是框架的主體內容
def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    path = environ['PATH_INFO']
    for url_tuple in urlpatterns:
        if url_tuple[0] == path:
            data = url_tuple[1](environ) #environ要傳進去,由於處理邏輯裏面可能要用
            break
        else:
            data = b'sorry 404!,not found the page'
    return [data]
        #注意昂,咱們若是直接返回中文,沒有給瀏覽器指定編碼格式,默認是gbk,因此咱們須要gbk來編碼一下,瀏覽器才能識別
        # data='登錄成功!'.encode('gbk')

httpd = make_server('127.0.0.1', 8001, application)

print('Serving HTTP on port 8001...')
# 開始監聽HTTP請求:
httpd.serve_forever()

#整個框架寫好了,那麼咱們未來想添加一些新的功能,好比說有人想在網址裏面輸入http://127.0.0.1:8001/timer 來查看當前時間,你只須要兩步,寫一個url映射關係,寫一個應對的處理函數就搞定了,有了框架就不須要你在從新寫一遍這全部的邏輯了,簡單兩步搞定新功能

 

3.urls文件:

from views import login,auth,favicon,index,timer

#url與視圖函數的對應關係
urlpatterns=[
    ('/login',login),
    ('/auth/',auth),
    ('/favicon.ico',favicon),
    ('/',index),
    ('/timer',timer),

]

 

4.views文件:

import datetime
import webauth
from urllib.parse import parse_qs

def login(environ):
    with open('templates/login.html', 'rb') as f:
        data = f.read()
    return data

def auth(environ):
    # 登錄認證
    # 1.獲取用戶輸入的用戶名和密碼

    # 2.去數據庫作數據的校驗,查看用戶提交的是否合法
    # user_information = environ['']
    if environ.get("REQUEST_METHOD") == "POST":
        # 獲取請求體數據的長度,由於提交過來的數據須要用它來提取,注意POST請求和GET請求的獲取數據的方式不一樣
        try:
            request_body_size = int(environ.get('CONTENT_LENGTH', 0))
        except (ValueError):
            request_body_size = 0
        # POST請求獲取數據的方式
        request_data = environ['wsgi.input'].read(request_body_size)
        print('>>>>>', request_data)  # >>>>> b'username=chao&password=123',是個bytes類型數據
        print('?????', environ['QUERY_STRING'])  # ????? 空的,由於post請求只能按照上面這種方式取數據
        # parse_qs能夠幫咱們解析數據
        re_data = parse_qs(request_data.decode('utf-8'))  # 將bytes類型數據轉碼
        print('拆解後的數據', re_data)  # 拆解後的數據 {'username': ['wu'], 'password': ['456']}
        username = re_data['username'][0]
        password = re_data['password'][0]
        print(username, password)
        # 進行驗證
        status = webauth.auth(username, password)
        if status:
            # 3.將相應內容返回
            with open('success.html', 'rb') as f:
                data = f.read()
        else:
            data = b'auth error'
    if environ.get("REQUEST_METHOD") == "GET":
        # GET請求獲取數據的方式,只能按照這種方式取
        print('?????', environ['QUERY_STRING'])  # ????? username=chao&password=123,是個字符串類型數據
        request_data = environ['QUERY_STRING']

        # parse_qs能夠幫咱們解析數據
        re_data = parse_qs(request_data)
        print('拆解後的數據', re_data)  # 拆解後的數據 {'password': ['123'], 'username': ['chao']}
        username = re_data['username'][0]
        password = re_data['password'][0]
        print(username, password)
        # 進行驗證:
        status = webauth.auth(username, password)
        if status:
            # 3.將相應內容返回
            with open('templates/websuccess.html', 'rb') as f:
                data = f.read()
        else:
            data = b'auth error'
    return data

def favicon(environ):
    with open('wechat.ico','rb') as f:
        data = f.read()
    return data

def index(environ):
    with open('templates/index.html','rb') as f:
        data = f.read()
    return data

#查看當前時間的
def timer(environ):
    data = str(datetime.datetime.now()).encode('utf-8')
    return data

 

5.用戶名密碼驗證 webauth文件:

#對用戶名和密碼進行驗證
def auth(username,password):
    import pymysql
    conn = pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123',
        database='day53',
        charset='utf8'
    )
    print('userinfo',username,password)
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    sql = 'select * from userinfo where username=%s and password=%s;'
    res = cursor.execute(sql, [username, password])
    if res:
        return True
    else:
        return False

 

6.templates 文件夾下html文件:

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<a href="http://127.0.0.1:8001/login">請登陸</a>

</body>
</html>

 

login.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<!--若是form表單裏面的action什麼值也沒給,默認是往當前頁面的url上提交你的數據,因此咱們能夠本身指定數據的提交路徑-->
<!--<form action="http://127.0.0.1:8001/auth/" method="post">-->
<form action="http://127.0.0.1:8001/auth/" method="get">
    用戶名<input type="text" name="username">
    密碼 <input type="password" name="password">
    <input type="submit">
</form>

</body>
</html>

 

websuccess.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        h1{
            color:red;
        }
    </style>
</head>
<body>
<h1>恭喜你登錄成功!</h1>

</body>
</html>

模板渲染JinJa2

  上面的代碼實現了一個簡單的動態頁面(字符串替換),我徹底能夠從數據庫中查詢數據,而後去替換我html中的對應內容(專業名詞叫作模板渲染,你先渲染一下,再給瀏覽器進行渲染),而後再發送給瀏覽器完成渲染。 這個過程就至關於HTML模板渲染數據。 本質上就是HTML內容中利用一些特殊的符號來替換要展現的數據。 我這裏用的特殊符號是我定義的,其實模板渲染有個現成的工具: jinja2

 下載:在cmd命令提示符中輸入或者pycharm中terminal

pip install jinja2

來一個html文件,index,html,內容以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>姓名:{{name}}</h1>
    <h1>愛好:</h1>
    <ul>
        {% for hobby in hobby_list %}
        <li>{{hobby}}</li>
        {% endfor %}
    </ul>
</body>
</html>

使用jinja2渲染index2.html文件,建立一個python文件:

from wsgiref.simple_server import make_server
from jinja2 import Template

def index():
with open("index.html", "r",encoding='utf-8') as f:
data = f.read()
template = Template(data) # 生成模板文件
ret = template.render({"name": "于謙", "hobby_list": ["抽菸", "喝酒","燙頭"]}) # 把數據填充到模板裏面
return [bytes(ret, encoding="utf8"), ]

# 定義一個url和函數的對應關係
URL_LIST = [
("/index", index),
]

def run_server(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 設置HTTP響應的狀態碼和頭信息
url = environ['PATH_INFO'] # 取到用戶輸入的url
func = None # 將要執行的函數
for i in URL_LIST:
if i[0] == url:
func = i[1] # 去以前定義好的url列表裏找url應該執行的函數
break
if func: # 若是能找到要執行的函數
return func() # 返回函數的執行結果
else:
return [bytes("404沒有該頁面", encoding="utf8"), ]


if __name__ == '__main__':
httpd = make_server('', 8001, run_server)
print("Serving HTTP on port 8001...")
httpd.serve_forever()

 

 

 從數據庫中查詢數據,來填充頁面

使用pymysql鏈接數據庫:

conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="xxx", db="xxx", charset="utf8")
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("select name, age, department_id from userinfo")
user_list = cursor.fetchall()
cursor.close()
conn.close()

 建立一個測試的user表:

CREATE TABLE user(
  id int auto_increment PRIMARY KEY,
  name CHAR(10) NOT NULL,
  hobby CHAR(20) NOT NULL
)engine=innodb DEFAULT charset=UTF8;

模板的原理就是字符串替換,咱們只要在HTML頁面中遵循jinja2的語法規則寫上,其內部就會按照指定的語法進行相應的替換,從而達到動態的返回內容。

相關文章
相關標籤/搜索