手动搭建简易web框架与django框架简介


目录
  • 纯手写简易web框架
  • 基于wsgiref模块
  • 动静态网页
  • 简单了解jinja2模块
  • 框架请求流程
  • python主流web框架
  • django框架
    • 简介
    • 应用app
    • 命令操作django
    • pycharm操作django
    • django主要文件介绍

纯手写简易web框架

第一步:搭建简易版本服务端

import socket

server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    sock, addr = server.accept()
    data = sock.recv(1024).decode('utf8')
    print(data)
    sock.send(b'hello')

第二步:遵循HTTP协议给浏览器发送消息

import socket

server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    sock, addr = server.accept()
    data = sock.recv(1024).decode('utf8')
    print(data)
    sock.send(b'HTTP1.1 200 OK\r\n\r\n')
    sock.send(b'hello world!')

第三步:启动服务端后浏览器输入127.0.0.1:8080测试是否能获取服务端的消息

第四步:基于不同的后缀响应不同的内容,如:127.0.0.1:8080/login、127.0.0.1:8080/register

import socket

server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    sock, addr = server.accept()
    data = sock.recv(1024).decode('utf8')
    sock.send(b'HTTP1.1 200 OK\r\n\r\n')
    # 切割浏览器的请求消息,只获取后缀内容
    new_data = data.split(' ')[1]
    # 根据后缀的不同返回不同的内容
    if new_data == '/login':
        sock.send(b'welcome login')
    elif new_data == '/register':
        sock.send(b'welcome register')
    else:
        sock.send(b'404 error')

搭建完成,但是这种搭建方式有许多缺陷:

  1. 服务端起始代码过于重复
  2. 针对HTTP请求数据没有完善的处理方式
  3. 并发量问题

基于wsgiref模块

wsgiref模块可以帮你快速处理请求数据与响应数据,这个模块会把请求数据处理成字典类型的数据。

利用wsgiref模块搭建服务端

from wsgiref import simple_server

def run(request, response):
    """
    :param request: 请求相关的数据
    :param response: 响应相关的数据
    :return: 返回给客户端的展示数据
    """
    print(request)  # 查看请求数据
    response('200 OK', [])  # 固定编写,遵循http协议
    current_path = request.get("PATH_INFO")  # 获取ip地址中的后缀
    if current_path == '/login':
        return [b'welcome login']
    elif current_path == '/register':
        return [b'welcome register']
    return [b'404 error']


if __name__ == '__main__':
    server = simple_server.make_server('127.0.0.1', 8080, run)
    '''一致监听本机8080端口 一旦有请求访问 自动触发run方法的执行'''
    server.serve_forever()  # 服务端永久运行

缺陷:

  • 如果网站很多,是不是就是一味的添加elif
  • 每个分支下的功能根据业务逻辑的不同可能会比较复杂

优化

第一步:将匹配和功能封装成元组和函数

from wsgiref import simple_server

def login():
    return 'welcome login'

def register():
    return 'welcome register'

urls = (
    ('/login', login),
    ('/register', register),
)

def run(request, response):
    """
    :param request: 请求相关的数据
    :param response: 响应相关的数据
    :return: 返回给客户端的展示数据
    """
    print(request)  # 查看请求数据
    response('200 OK', [])  # 固定编写,遵循http协议
    current_path = request.get("PATH_INFO")  # 获取ip地址中的后缀
    for url in urls:
        if current_path == url[0]:
            res = url[1]()
            break
    else:
        res = '404 error'
    return [res.encode('utf8')]

if __name__ == '__main__':
    server = simple_server.make_server('127.0.0.1', 8080, run)
    '''一致监听本机8080端口 一旦有请求访问 自动触发run方法的执行'''
    server.serve_forever()  # 服务端永久运行

第二步:根据功能的不同拆分成不同的py文件

views.py:业务逻辑的编写

def login(request):
    return 'welcome login'

def register(request):
    return 'welcome register'

urls.py:存储对应关系

from views import *
urls = (
    ('/login', login),
    ('/register', register),
)

服务端:

from wsgiref import simple_server
from urls import urls

def run(request, response):
    response('200 OK', [])  # 固定编写,遵循http协议
    current_path = request.get("PATH_INFO")  # 获取ip地址中的后缀
    for url in urls:
        if current_path == url[0]:
            res = url[1](request)
            break
    else:
        res = '404 error'
    return [res.encode('utf8')]

if __name__ == '__main__':
    server = simple_server.make_server('127.0.0.1', 8080, run)
    '''一致监听本机8080端口 一旦有请求访问 自动触发run方法的执行'''
    server.serve_forever()  # 服务端永久运行

基于上述优化之后,整个项目结构清晰,管理维护都很方便!并且拆分完后以后要想新增功能,只需要在urls.py中添加对应关系 view.py中编写函数。

补充

业务函数的代码中,可能会频繁的使用到不同的html页面,为了避免文件类型的混乱,会单独开设一个文件夹存储所有的html文件:templates文件夹。

项目中的html文件,也有可能需要用到css、js、第三方框架文件,这些文件都是很少做改动的文件,可以统一放到:static文件夹。

动静态网页

静态网页:页面上的数据是不会改变的。

动态网页:页面上的数据是通过代码动态获取的,实时可变。

编写简易动态网页

第一步:在项目的templates文件夹下创建get_time.html




    
    Title


    

时间:time_show

第二步:在上面代码的基础上,对views.py和urls.py文件添加以下内容:

views.py:添加新函数

def get_time(request):
    # 1.获取当前时间
    import time
    c_time = time.strftime('%Y-%m-%d %X')
    # 2.读取html文件
    with open(r'templates/get_time.html', 'r', encoding='utf8') as f:
        data = f.read()
    # 3.思考:如何给字符串添加一些额外的字符串数据>>>:字符串替换
    new_data = data.replace('time_show', c_time)
    return new_data

urls.py:修改urls变量

from views import *
urls = (
    ('/login', login),
    ('/register', register),
    ('/get_time', get_time),
)

运行服务端,输入127.0.0.1/get_time,此时展示的页面就是动态页面,每次刷新都会从后端获取数据并更新。

这种方式前端无法操作传来的数据,那么如果想要让前端可以操作数据呢?比如把字典传过去,让前端自行操作字典类型数据,这就需要用到一个第三方模块:jinja2模块。

简单了解jinja2模块

在编写前后端不分离项目的时候,可以使用该模块提供的模板语法简单快速的在html页面是使用类似于后端的代码语法操作数据。

jinja2模块属于第三方模块,需要自行下载:

pip install jinja2

在项目的templates文件夹下创建get_dict.html:




    
    Title


    

字典展示

{{ user.name }}

{{ user.pwd }}

{{ user.hobby }}

列表循环展示

{% for i in new_list %} 元素:{{ i }} {% endfor %}

views.py:添加函数

from jinja2 import Template
def get_dict(request):
    user_dict = {'name': 'jason', 'pwd': 123, 'hobby': 'read'}
    new_list = [11, 22, 33, 44, 55, 66]
    with open(r'templates/get_dict.html', 'r', encoding='utf8') as f:
        data = f.read()
    temp_obj = Template(data)
    res = temp_obj.render({'user':user_dict,'new_list':new_list})
    # 给页面传递一个变量名是user 值是user_dict对应的值的数据
    return res

urls.py:修改urls变量:

from views import *
urls = (
    ('/login', login),
    ('/register', register),
    ('/get_time', get_time),
    ('/get_dict', get_dict),
)

访问127.0.0.1/get_dict。

框架请求流程

仅限于我们自己编写的web框架

urls.py:路由层

  • 后缀与函数名对应关系
  • 后缀专业名词称之为'路由'
  • 函数名专业名词称之为'视图函数'

views.py:视图层

  • 专门编写业务逻辑代码
  • 可以是函数,也可以是类
  • 函数专业名词称之为'视图函数'
  • 类专业名词称之为'视图类'

templates文件夹:模板层

  • 专门存储html文件
  • html文件专业名词称之为'模板文件'

python主流web框架

django:大而全,自带的功能非常的多,但是有时候会略显笨重,类似于'航空母舰'。

flask:小而精,自带的功能非常的少,但是第三方模块非常的多,类似于'游骑兵'。

flask的第三方模块加到一起甚至比django还多,并且也越来越像django;flask由于过多的依赖于第三方模块,有时候也会受制于第三方模块。

tornado:异步非阻塞框架,速度极快,甚至可以用于充当游戏服务器。

django框架

简介

版本

  • django3.X:默认支持异步功能
  • django2.X:默认不支持异步
  • django1.X:默认不支持异步

下载使用

建议使用1.11.X版本

pip install django==1.11.11 

验证是否下载成功

cmd窗口直接输入django-admin,有反应就是成功了。

应用app

django本身类似于是一个空壳子,真正的功能是由里面的各个应用决定。django框架就相当于是一所大学,应用相当于是大学里面的各个学院。

在使用django框架时,会先创建一个空的django项目,然后根据功能的不同创建不同的应用。

创建应用之后,一定要去配置文件中注册才能生效。

比如我创建一个应用,名为app01,创建后给settings.py文件中INSTALLED_APPS配置添加应用名称。

命令操作django

1.创建django项目

django-admin startproject 项目名

2.进入django项目目录

cd 项目名  

3.创建app应用

python manage.py startapp 应用名

4.启动django项目

python manage.py runserver IP地址:端口号

5.浏览器访问IP地址:端口号

pycharm操作django

1.file-->new project,选择django,输入信息,创建,选择此窗口打开。

2.创建应用:tools-->Run manage.py Task

在弹出来的终端输入创建应用命令:

startapp 应用名

3.修改端口号:

4.启动项目:

5.浏览器访问

django主要文件介绍

djangoProject:项目文件名
{
    app01:应用文件夹
    {	
        migrations文件夹:数据迁移记录
     	admin.py:django自带的后台管理
        apps.py:用于app的注册
        models.py:专门用于操作数据库
     	views.py:视图层
    }
    djangoProject:项目同名文件夹
    {
        settings.py:项目配置文件
        urls.py:路由层
    }
    templates:模板层
    manage.py:django入口文件,很多命令都需要该文件支持
    db.sqlite3:django启动之后才会生成的文件,其实就是django自带的小型数据库
}