Django导读

一 .Django框架介绍

  Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的框架模式,即模型M,视图V和控制器C。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。

二.WEB应用

  web应用值得之运行在浏览器(客户端)上的应用,具有b/s或者c/s架构,b/s架构指的是浏览器服务器架构,当前java与python语言采用的就是这一套架构开发的web,而c/s架构指的是客户端服务器架构,普遍用于C++。这两种架构的底层均是基于socket编程的。

三.Python的WEB框架

  python中主要有三大框架分别是:Django、Flask、Tornado。这三类方法各有各的优点。主要分别体现在socket传输、页面路由以及模板渲染这三方面。具体区别如下:

四. 使用socket自定义一个服务器

  浏览器与服务器之间进行连接,必须遵循一个协议——http协议。

# HTTP(HyperText Transport Protocol)是超文本传输协议
# 基于TCP/IP协议基础上的应用层协议,底层实现仍为socket
# 基于请求-响应模式:通信一定是从客户端开始,服务器端接收到客户端一定会做出对应响应
# 无状态:协议不对任何一次通信状态和任何数据做保存
# 无连接:一次连接只完成一次请求-响应,请求-响应完毕后会立即断开连接
什么是HTTP协议

  HTTP协议的工作原理(事务)如下: #一次http操作称之为一个事务,工作过程可分为四步

  1.客户端与服务端建立连接

  2.客户端发生一个http协议指定格式的请求

  3.服务端接收请求后,响应一个http协议指定格式的响应

  4.客户端将服务器的响应现实展示给用户

'''
POST / HTTP/1.1\r\n
Host: 127.0.0.1:8001\r\n
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n
\r\n
usr=abc&pwd=123
'''
http的请求报文
# 响应行  响应头  响应体
'''
HTTP/1.1 200 OK\r\n
Content-type:text/html\r\n
\r\n
Login Success
'''
http的响应报文
import socket

server = socket.socket()
server.bind(("127.0.0.1",8809))
server.listen(5)
print("服务启动:http://127.0.0.1:8809")

# 1.浏览器采用http协议方式发生请求
while True:
    browser,_ =server.accept()

    data = browser.recv(1024)
    print(data.decode("utf-8"))
    # 要遵循http协议返回数据:响应行(必须) 响应头 响应体
    browser.send(b'HTTP/1.1 200 OK\r\n')  #响应行(必须的),以\r\n结束
    browser.send(b'Content-type:text/html\r\n') #响应头(可选),服务于响应体
    browser.send(b'\r\n')  # 响应规则与响应体内容之间还需要一个\r\n标识分割
    browser.send(b'<h1>hello world</h1>')  # 响应体(可选)
    browser.close()
自定义socket完成server

   服务器与浏览器建立连接后,就可以像浏览器发送数据,浏览器接收解析之后,便会展示给用户看。在自定义的socket完成服务器中,可以修改返回的数据,完善响应体,使得浏览器能进行页面跳转,增加标签等操作。

扫描二维码关注公众号,回复: 5318570 查看本文章
# 字符串
client.send(b'HTTP/1.1 200 OK\r\n')
client.send(b'\r\n')
client.send(b'Normal Socket Web')
增加字符串
# html代码,请求头要设置支持html代码
client.send(b'HTTP/1.1 200 OK\r\n')
client.send(b'Content-type:text/html\r\n')
client.send(b'\r\n')
client.send(b'<h1>Normal Socket Web</h1>')
增加html标签
# html文件(同级目录建立一个index.html页面)
client.send(b'HTTP/1.1 200 OK\r\n')
client.send(b'Content-type:text/html\r\n')
client.send(b'\r\n')
# 利用文件方式读取页面
with open('index.html', 'rb') as f:
    dt = f.read()
client.send(dt)
进行网页的跳转

  当服务器接收到浏览器发送的请求后,我们可以根据浏览器的发送的数据,进行业务逻辑的分发,这个过程被称为路由分发。实质为匹配url地址的后面几位,将其利用字典,函数等操作跳转至对应接口函数。

# 分析接收到的数据
data = client.recv(1024)
# 保证接收到的数据作为字符串进行以下处理
data = str(data, encoding='utf-8')
# 拆分出地址位
route = data.split('\r\n')[0].split(' ')[1]
# 匹配地址,做出不同的响应
if route == '/index':
    with open('index.html', 'rb') as f:
        dt = f.read()
elif route == '/login':  # 新建login页面
    with open('login.html', 'rb') as f:
        dt = f.read()
else:
    dt = b'404'
client.send(dt)

#if判断后可以使用字典,函数等取值方式代替,介绍代码冗余,提高代码可读性。
修改接收数据,模拟后台路由

五. 状态码

# 1打头:消息通知
# 2打头:请求成功
# 3打头:重定向
# 4打头:客户端错误
# 5打头:服务器端错误
import socket

server = socket.socket()
server.bind(("127.0.0.1",8809))
server.listen(5)
print("服务启动:http://127.0.0.1:8809")


def login():
    return b'login success'
def index():
    return b'this is index'

def ico():
    #设置页面图标
    with open('dog.jpg','rb')as f:
        data = f.read()
    return data

method_dic={
    "/":index,
    "/login":login,
    "/favicon.ico":ico
}
# 1.浏览器采用http协议方式发生请求
while True:
    browser,_ =server.accept()

    data = str(browser.recv(1024).decode("utf-8"))  #格式化收到的数据
    #http://127.0.0.1:8809/login
    print(data)
    data_method = data.split('\r\n')[0].split(' ')[1] #第一个split取得#GET /index HTTP/1.1,第二个split取得/index
    res = b'404' #默认找不到页面
    if data_method in method_dic:
        res = method_dic[data_method]()

    # 要遵循http协议返回数据:响应行(必须) 响应头 响应体
    browser.send(b'HTTP/1.1 200 OK\r\n')  #响应行(必须的),以\r\n结束
    browser.send(b'Content-type:text/html\r\n') #响应头(可选),服务于响应体
    browser.send(b'\r\n')  # 响应规则与响应体内容之间还需要一个\r\n标识分割
    browser.send(res)
    browser.close()
socket自定义服务器+路由分发+数据库处理完成登录(未实现登录逻辑)

六. wsgiref

  由于我们自定义socket的服务器,可能会导致不稳定,并发差的问题,因此可以使用第三方服务器这种方式来解决这个问题,wsgiref模块中就帮我们封装看一个服务器,Django中的服务器也是这个原理,接下来我来使用wsgiref模块和以上的知识(使用post类型的表单)来完成一个完整的登录功能。

login.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>登录</title>
</head>
<body>
<form action="http://127.0.0.1:8809/login" method="POST">
    <div>
        <label for="user">用户名:</label>
        <input type="text" name="user">
    </div>
    <div>
        <label for="pwd">密码:</label>
        <input type="password" name="pwd">
    </div>

    <input type="submit" value="登录">
</form>
</body>
</html>

server.py

from wsgiref import simple_server
from urls import method_dic
PORT = 8809

def app(environ,response):
    response("200 OK", [('Content-type', 'text/html')])
    url = environ.get("PATH_INFO")
    user_dic = {}
    res = b'404'
    print(environ.get("REQUEST_METHOD"))
    if environ.get("REQUEST_METHOD") == "POST"and environ['CONTENT_LENGTH']:  #如果是post表单提交的信息,并且表单提交的数据有内容
        length = int(environ['CONTENT_LENGTH'])
        res = environ['wsgi.input'].read(length).decode('utf-8')
        post_str_list = res.split("&")  #[user=abc,pwd=123]
        for post_str in post_str_list:
            k_v_list = post_str.split("=")  #[user,abc]、[pwd、123]
            user_dic[k_v_list[0]]=k_v_list[1]  #这段代码是为了获取表单提交的用户名与密码
    print(user_dic)
    if url in method_dic:
        res = method_dic.get(url)(user_dic)
    return [res]





if __name__ == '__main__':
    server = simple_server.make_server("127.0.0.1",PORT,app)
    print("服务启动:http://127.0.0.1:%s" % PORT)
    server.serve_forever()

urls.py

from views import *
method_dic = {
    "/":index,
    "/login":login,
    "favicon.ico":ico
}

views.py

import pymysql


def login(user_dic):
    user = user_dic.get("user")
    pwd = user_dic.get("pwd")
    conn = pymysql.connect(
        host = "127.0.0.1",
        db = "dj1",
        user = "root",
        password = "123"
    )
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    sql = "select * from user where user=%s and pwd = %s"
    row = cursor.execute(sql,args=[user,pwd])
    if row:
        return b'login success'
    return b'login failed'

def ico(user_dic):
    with open('dog.jpg','rb')as f:
        data = f.read()
    return data


def index(user_dic):
    return b'this is index'

需要注意:运行服务后,需要手动打开login.html文件,才能测试。

猜你喜欢

转载自www.cnblogs.com/846617819qq/p/10433506.html