web框架

  web本质就是一个socket服务端,而用户浏览器就是一个socket客户端.但是不

  同的浏览器(客户端)就有不同的规则,所以在与服务端互动时就需要统一格式,

  HTTP协议主要规定可客户端与服务器之间的通信格式.

  首先看服务端接收到的消息:

import socket

sk = socket.socket()
sk.bind(("127.0.0.1", 80))
sk.listen()


while True:
    conn, addr = sk.accept()
    data = conn.recv(8096)
    print(data)  # 将浏览器发来的消息打印出来
    conn.send(b"OK")
    conn.close()

  输出

b'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/64.0.3282.186 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
DNT: 1
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: csrftoken=RKBXh1d3M97iz03Rpbojx1bR6mhHudhyX5PszUxxG3bOEwh1lxFpGOgWN93ZH3zvrnrn
'

  

  再看访问博客园时浏览器收到的响应消息:

 

  点击view source之后显示如下图:

  

  HTTP协议对收发消息的格式要求:

  每个HTTP请求和响应都遵循相同格式,一个HTTP包含header和body俩部

  分,其中body是可选的.HTTP响应的header中有一个content-type表明响应

  的内容格式.如:text/html 表示HTML网页.

  HTTP GET请求格式:

 

  HTTP响应格式:

  自定义web框架

  

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 8000))
sock.listen()

while True:
    conn, addr = sock.accept()
    data = conn.recv(8096)
    # 给回复的消息加上响应状态行
    conn.send(b"HTTP/1.1 200 OKrnrn")
    conn.send(b"OK")
    conn.close()

 

  根据不同的路径返回不同的内容:

"""
根据URL中不同的路径返回不同的内容
"""

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080))  # 绑定IP和端口
sk.listen()  # 监听


while 1:
    # 等待连接
    conn, add = sk.accept()
    data = conn.recv(8096)  # 接收客户端发来的消息
    # 从data中取到路径
    data = str(data, encoding="utf8")  # 把收到的字节类型的数据转换成字符串
    # 按rn分割
    data1 = data.split("rn")[0]
    url = data1.split(' ')[1]  # url是我们从浏览器发过来的消息中分离出的访问路径
    conn.send(b'HTTP/1.1 200 OKrnrn')  # 因为要遵循HTTP协议,所以回复的消息也要加状态行
    # 根据不同的路径返回不同内容
    if url == "/index/":
        response = b"index"
    elif url == "/home/":
        response = b"home"
    else:
        response = b"404 not found!"

    conn.send(response)
    conn.close()

 

  根据不同的路径返回不同内容(函数版)

"""
根据URL中不同的路径返回不同的内容--函数版
"""

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080))  # 绑定IP和端口
sk.listen()  # 监听


# 将返回不同的内容部分封装成函数
def index(url):
    s = "这是{}页面!".format(url)
    return bytes(s, encoding="utf8")


def home(url):
    s = "这是{}页面!".format(url)
    return bytes(s, encoding="utf8")


while 1:
    # 等待连接
    conn, add = sk.accept()
    data = conn.recv(8096)  # 接收客户端发来的消息
    # 从data中取到路径
    data = str(data, encoding="utf8")  # 把收到的字节类型的数据转换成字符串
    # 按rn分割
    data1 = data.split("rn")[0]
    url = data1.split()[1]  # url是我们从浏览器发过来的消息中分离出的访问路径
    conn.send(b'HTTP/1.1 200 OKrnrn')  # 因为要遵循HTTP协议,所以回复的消息也要加状态行
    # 根据不同的路径返回不同内容,response是具体的响应体
    if url == "/index/":
        response = index(url)
    elif url == "/home/":
        response = home(url)
    else:
        response = b"404 not found!"

    conn.send(response)
    conn.close()

 

  根据不同的路径返回不同的内容(函数进阶)

  

"""
根据URL中不同的路径返回不同的内容--函数进阶版
"""

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080))  # 绑定IP和端口
sk.listen()  # 监听


# 将返回不同的内容部分封装成函数
def index(url):
    s = "这是{}页面!".format(url)
    return bytes(s, encoding="utf8")


def home(url):
    s = "这是{}页面!".format(url)
    return bytes(s, encoding="utf8")


# 定义一个url和实际要执行的函数的对应关系
list1 = [
    ("/index/", index),
    ("/home/", home),
]

while 1:
    # 等待连接
    conn, add = sk.accept()
    data = conn.recv(8096)  # 接收客户端发来的消息
    # 从data中取到路径
    data = str(data, encoding="utf8")  # 把收到的字节类型的数据转换成字符串
    # 按rn分割
    data1 = data.split("rn")[0]
    url = data1.split()[1]  # url是我们从浏览器发过来的消息中分离出的访问路径
    conn.send(b'HTTP/1.1 200 OKrnrn')  # 因为要遵循HTTP协议,所以回复的消息也要加状态行
    # 根据不同的路径返回不同内容
    func = None  # 定义一个保存将要执行的函数名的变量
    for i in list1:
        if i[0] == url:
            func = i[1]
            break
    if func:
        response = func(url)
    else:
        response = b"404 not found!"

    # 返回具体的响应消息
    conn.send(response)
    conn.close()

 

  让网页动态起来

  选择使用字符串替换来实现这个需求(这里使用时间戳来模拟动态数据)

"""
根据URL中不同的路径返回不同的内容--函数进阶版
返回HTML页面
让网页动态起来
"""

import socket
import time

sk = socket.socket()
sk.bind(("127.0.0.1", 8080))  # 绑定IP和端口
sk.listen()  # 监听


# 将返回不同的内容部分封装成函数
def index(url):
    with open("index.html", "r", encoding="utf8") as f:
        s = f.read()
        now = str(time.time())
        s = s.replace("@@oo@@", now)  # 在网页中定义好特殊符号,用动态的数据去替换提前定义好的特殊符号
    return bytes(s, encoding="utf8")


def home(url):
    with open("home.html", "r", encoding="utf8") as f:
        s = f.read()
    return bytes(s, encoding="utf8")


# 定义一个url和实际要执行的函数的对应关系
list1 = [
    ("/index/", index),
    ("/home/", home),
]

while 1:
    # 等待连接
    conn, add = sk.accept()
    data = conn.recv(8096)  # 接收客户端发来的消息
    # 从data中取到路径
    data = str(data, encoding="utf8")  # 把收到的字节类型的数据转换成字符串
    # 按rn分割
    data1 = data.split("rn")[0]
    url = data1.split()[1]  # url是我们从浏览器发过来的消息中分离出的访问路径
    conn.send(b'HTTP/1.1 200 OKrnrn')  # 因为要遵循HTTP协议,所以回复的消息也要加状态行
    # 根据不同的路径返回不同内容
    func = None  # 定义一个保存将要执行的函数名的变量
    for i in list1:
        if i[0] == url:
            func = i[1]
            break
    if func:
        response = func(url)
    else:
        response = b"404 not found!"

    # 返回具体的响应消息
    conn.send(response)
    conn.close()

 

  python web框架分类

   a.  收发socket消息 , 按照HTTP协议解析消息 web服务

    wsgiref,gunicorn,uWSGI

   b. 字符串替换

   c.业务逻辑处理

  

  web 应用程序:

    自己实现 a b c 的     tornado

    自己实现b c 使用别人a      Django

    自己实现c 使用别人的a b   flask

      

  安装:

  在py的安装文件中找出scripts文件夹,shift+右键 打开powershell:

    pip install django==1.11.11

 

  创建Django项目:

  在cmd命令行中创建: django-admin startproject 项目名

  在pycharm中创建: 专业版(自己建)      非专业版(没有)

 

  在命令行中运行 Django项目:  

    Python manage.py runserver 127.0.0.1:8000(默认本机端口,可自己

    设置)

    停止 : Ctrl + c

     

  目录介绍:

mysite/ 
├── manage.py  # 管理文件 
└── mysite  # 项目目录
    ├── __init__.py
    ├── settings.py  # 配置 
    ├── urls.py  # 路由 --> URL和函数的对应关系
    └── wsgi.py  # runserver命令就使用wsgiref模块做简单的web server

 

  db.sqlite3  Django 开发环境默认的文件数据库

 

  模板文件配置(配置调用的文件路径):

  

#跟html相关的文件配置
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "template")],# 路径拼接 BASE_DIR(指项目的根目录)和template文件
    'APP_DIRS': True,
     'OPTIONS': {
      'context_processors': [
        
'django.template.context_processors.debug',
         'django.template.context_processors.request',
         'django.contrib.auth.context_processors.auth',
        
'django.contrib.messages.context_processors.messages',
       ],
     },
   },
]

 

  静态文件配置(js css images等文件路径):

  在调用时能够依次查找需要调用的文件了路径

STATIC_URL = '/static/'  # HTML中使用的静态文件夹前缀
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),  # 静态文件存放位置,进行静态文件编辑可以在static文件中进行。
]

  

   Django三种基础模块

  

from django.shortcuts import HttpResponse, render, redirect 

  HttpResponse  内部传入一个字符串参数,返回给浏览器.
例如:
  
def index(request):
    #业务逻辑
    return HttpResponse('ok')

 

  render  

  除request参数外还接受一个待渲染的模板文件和一个保存具体数据的字典参数。

  将数据填充进模板文件,最后把结果返回给浏览器。

def index(request):
    # 业务逻辑代码
    return render(request, "index.html", {"name": "alex", "hobby": ["烫头", "泡吧"]})

 

  redirect

  接受一个URL参数 , 表示跳转到指定的URL.

def index(request):
    # 业务逻辑代码
    return redirect("/home/")

 

  重新定向

  普通请求响应: 浏览器发一个消息,服务器回一个

  重定向请求响应: 浏览器发一个消息,服务器发一个跳转的消息,浏览器

    根据这条消息向服务器发送请求,服务器再返回一条信息.

 

 

  浏览器(客户端)与服务端的交互过程:

  ---浏览器发送请求(地址栏输入URL)

  --- 根据URL匹配要访问的路径即查找要执行的函数

     --- Django找到调用的函数,把与请求相关的数据由request参数进行传输.

     --- 去指定文件夹找到相关文件,打开读取内容,按照HTTP响应的格式给浏

    览器返回读取内容

  --- 浏览器收到返回的响应消息并按照HTTP格式显示消息.

 

 

 

 

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!