DJango基础框架简介

心不动则不痛 提交于 2019-12-22 05:55:07

一:web框架基础简介

【1】web框架本质

  (1)web本质也是C/S架构 

  (2)浏览器:客户端

  (2)服务端:服务端

 

【2】web框架自定义

复制代码
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(6)


while True:
    conn ,addr = server.accept()
    # 字符串
    recv_data = conn.recv(1024).decode('utf-8')
    print(recv_data)
    conn.send(b'hello world')
    conn.close()
复制代码

(1)客户端结果展示

 

(2)服务端结果展示

'''b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-User: ?1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\nSec-Fetch-Site: none\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n\r\n'''

PS:客户端无法正常接收数据的原因

(1)首先浏览器向服务端发送请求的时候 这个数据怎么发送 格式是什么样式

(2)不同的网站可能对发送方式定义的不一样 如果太多不一样 导致整个互联网紊乱

(3)因此我们使用同一标准HTTP协议

 

【3】HTTP协议版本

复制代码
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(6)


while True:
    conn ,addr = server.accept()
    # 字符串
    recv_data = conn.recv(1024)
    # HTTP版本 响应状态码 换行符
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    conn.send(b'hello world')
    conn.close()
复制代码

 

二:Web框架修正版

【1】根据用户请求的url不同返回相应的数据

(1)作用:每个用户可能请求的数据不同 根据用户请求的结果不同 返回不同的数据

(2)思路:

  (1)首先需要获取用户输入的路径

  (2)获取用户的路径根据不同的路径做不同从处理

例如:

import socket

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

while True:
    conn, addr = server.accept()
    # 拿到用户传入的数据 将其转为字符串状态
    recv_data = conn.recv(1024).decode('utf-8')
    print(recv_data)  # 字符串
    
    # 将获取的字符串进行切割获取列表
    path_list = recv_data.split('\r\n')[0]
    
    # 列表取索引获取访问路径
    current_path = path_list.split(' ')[1]
    
    print(current_path)  # /index

    # 根据HTTP协议进行数据交互
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')

    # 根据访问路径不同 返回不同的结果
    if current_path == '/index':
        conn.send(b'index')
    elif current_path == '/home':
        conn.send(b'home')

    #     访问资源不存 返回404
    else:
        conn.send(b'404 error')
View Code
'''
D:\Softwares\python3.6\python.exe "E:/work station/day51/django基础版本.py"

请求首行
GET / 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 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Sec-Fetch-Site: cross-site
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

\r\n

请求体:用户没传入

   # conn.send(b'HTTP/1.1 200 OK \r\n\r\n')
View Code

【2】路由与视图函数对应关系

(1)作用:

  (1)上述代码解决了根据不同的url返回不同的结果

  (2)但是假如有多个条件语句 需要写大量的条件判断 这样肯定是不合理的

(2)解决办法

  (1)创建路由与函数的对应关系 通过路由来执行不同的功能

例如:

import socket

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


def index(current_path):
    response = f'hello{current_path}'
    # 将字符串转换成二进制传输
    return bytes(response,encoding='utf-8')


def home(current_path):
    response = f'hello{current_path}'
    return bytes(response, encoding='utf-8')

# 创建路由与视图函数关系 以后添加新的功能 直接添加路由与对应的视图函数即可
url_list = [
    ('/index', index),
    ('/home', home)
]

while True:
    conn, addr = server.accept()
    # 拿到用户传入的数据 将其转为字符串状态
    recv_data = conn.recv(1024).decode('utf-8')

    # 将获取的字符串进行切割获取列表
    path_list = recv_data.split('\r\n')[0]

    # 列表取索引获取访问路径
    current_path = path_list.split(' ')[1]

    # 根据HTTP协议进行数据交互
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')

    func = None
    #  循环打印上述路由与视图关系列表
    for url in url_list:
        # 如果用户的url路径在上述列表中
        if url[0] == current_path:
            # 给上述函数赋值
            func = url[1]
            # 函数赋值之后 不需要再继续进行循环 直接打印即可
            break
    # 如果上函数被赋值  则调用函数
    if func:
        res = func(current_path)
    else:
        res = b'404 error'

    # 返回消息给客户端
    conn.send(res)
    conn.close()

三:动静态网页传递

(1)定义:

  (1)静态网页:数据是固定不变的

  (2)动态网页:数据是是可灵活变化的

(2)作用:

  (1)在上述代码中我们返回一些无用的字符串呈现给用户

  (2)在网页传递过程中我们传递相应的HTML文件呈现给用户

例如:

import socket

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


def index():
    # 对于python来说什么文件都是二进制 直接读取发送即可

    with open(r'ht1.html', 'rb') as file:
        data = file.read()
        return data


def home():
    with open(r'ht1.html', 'rb') as file:
        data = file.read()
        return data


url_dict = {
    '/index': index,
    '/home': home
}

while True:
    conn, addr = server.accept()
    recv_data = conn.recv(1024).decode('utf-8')
    url_list = recv_data.split('\r\n')[0]
    url_path = url_list.split(' ')[1]

    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    func = None
    for key, value in url_dict.items():
        if key == url_path:
            func = url_dict.get(key)
            break

    if func:
        res = func()

    else:
        res = b'404 error'

    conn.send(res)
    conn.close()
View Code
import socket

server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(66)
from datetime import datetime

func = None


def index():
    now_time = datetime.now().strftime('%Y-%m-%d %X')
    with open(r'h2.html', 'r', encoding='utf-8') as f:
        data = f.read()

        # 读取HTML中的数据 将其替换成我们想要传给用户的数据 这样类似于我们将后端数据插入到HTML数据中
        time = data.replace('SR', now_time).encode('utf-8')
        return time


def home():
    now_time = datetime.now().strftime('%Y-%m-%d %X')
    with open(r'h2.html', 'r', encoding='utf-8') as f:
        data = f.read()

        # 读取HTML中的数据 将其替换成我们想要传给用户的数据 这样类似于我们将后端数据插入到HTML数据中
        time = data.replace('SR', now_time).encode('utf-8')
        return time


url_list = {
    '/index': index,
    '/home': home
}

while True:
    conn, addr = server.accept()
    recv_data = conn.recv(1024).decode('utf-8')
    conn.send(b'HTTP/1.1 200OK\r\n\r\n')
    # 获取url地址
    url_path = recv_data.split('\r\n')[0].split(' ')[1]

    for key, value in url_list.items():
        if key == url_path:
            func = url_list.get(key)
            break
    if func:
        res = func()
    else:
        res = b'404 error'

    conn.send(res)
    conn.close()
View Code

四:服务器程序和应用程序

对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。

服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。

应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。

 

这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。

这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

WSGI(Web Server Gateway Interface)就是一种规范,它定义了使用Python编写的web应用程序与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦。

常用的WSGI服务器有uwsgi、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器。

 

五:WSGI/jinja2基本使用方式

【1】wsgi

(1)作用:

  (1)可以利用该模块替换我们自己写的socket server部分

  (2)将客户端传入的数据拆封成字典

  (3)将服务端传入给客户端的数据封装携带含有HTTP协议

例如:

# 导入模块
from wsgiref.simple_server import make_server


def index():
    data = b'hello world!'
    return data


def home():
    data = b'hello world!'
    return data


url_list = {
    '/index': index,
    '/home': home
}


def run_server(request, response):
    '''
    与客户端进行数据交互的函数
    :param request: 用户请求数据
    :param response: 服务端回应数据
    :return:
    '''
    print(request)  # 用户传来的数据自动变成字典格式
    response('200 ok', [])  # 回应客户端的格式

    url_path = request.get('PATH_INFO')
    func = None
    for key,value in url_list.items():
        if key == url_path:
            func = url_list.get(key)
            break
    if func:
        res = func()
    else:
        res = b'404 error'

    return [res]



if __name__ == '__main__':
    # 监听该地址加上端口号 如果有请求 直接调用该函数
    server = make_server('127.0.0.1', 8080, run_server)
    # 启动服务端
    server.serve_forever()
View Code

【2】jinja2与html结合

(1)作用:将后端传递给前端的数据进行页面渲染

例如:

from wsgiref.simple_server import make_server

# 导入模块
from jinja2 import Template


def index():
    data = b'hello world!'
    return data


def get_user():

    user_dict = {'username': 'SR', 'age': '123'}
    with open(r'get_user.html', 'r', encoding='utf-8') as f:
        data = f.read()
 
    #     生成一个对象
    temp = Template(data)

    # 用变量名指代字典 前端可以通过变量名获取字典 前端接受的变量与后端保持一致
    client_data = temp.render(data=user_dict).encode('utf-8')

    return client_data


url_list = {
    '/user': get_user,
    '/index': index,
}


def run(request, response):
    url_path = request['PATH_INFO']
    response('200 ok', [])
    func = None
    for key, value in url_list.items():
        if key == url_path:
            func = url_list.get(key)
            break

    if func:
        res = func()
    else:
        res = b'404 error'

    return [res]


if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    print('启动')
    server.serve_forever()
View Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>

</head>
<body>

<p>{{data}}</p>
    <p>{{data['username']}}</p>
    <p>{{data.age}}</p>
    <p>{{data.get('username')}}</p>
</body>
</html>
View Code

【3】jinja2与数据库进行结合

例如:

import pymysql
from jinja2 import Template
from wsgiref.simple_server import make_server



def mysql():
    conn = pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123',
        database='day51',
        charset='utf8',
        autocommit=True
    )
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    sql = "select * from user_info"
    affect_rows = cursor.execute(sql)
    data = cursor.fetchall()
    with open(r'my_sql.html','r',encoding='utf-8') as f:
        recv_data = f.read()
    temp = Template(recv_data)
    res = temp.render(user_list=data).encode('utf-8')
    return res


url_list = {
    '/mysql': mysql,

}



def run(request, response):
    url_path = request['PATH_INFO']
    response('200 ok', [])
    func = None
    for key, value in url_list.items():
        if key == url_path:
            func = url_list.get(key)
            break

    if func:

        res = func()
    else:
        res = b'404 error'

    return [res]


if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    print('启动')
    server.serve_forever()
View Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <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 class="text-center">id</th>
                    <th class="text-center">username</th>
                    <th class="text-center">age</th>
                </tr>
                </thead>
                <tbody>
                {%for user_dict in user_list%}
                <tr>
                    <td class="text-center">{{user_dict.id}}</td>
                    <td class="text-center">{{user_dict.name}}</td>
                    <td class="text-center">{{user_dict.age}}</td>
                </tr>
                {%endfor%}
                </tbody>
            </table>
        </div>

    </div>
</div>

</body>
</html>
View Code

六:Django安装使用

【1】命令行安装启动

(1)Django安装

pip3 install django=1.11.11

(2)检查Django是否安装成功

Django-admin

(3)创建Django项目

Django-admin startproject + 项目名称

(4)Django目录介绍

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

(5)创建Django应用

django-admin startapp  + 应用名
python manage.py startapp +  应用名

(6)目录应用介绍

└──  migrations     # 数据库迁移记录
    ├── admin.py    # 后台管理
    ├── apps.py     # 应用注册相关
    ├── models.py   # orm模型类
    └── test.py     # 测试文件
    └── views.py    # 视图函数

(6)启动Django服务

Django-admin manage.py runserver

 

 

 PS:

(1)命令行创建Django项目不会自动生成templates文件夹

(2)settings配置文件中也需要修改

(3)创建的项目需要在配置文件注册生效 否则无识别

 

七:Django基础三件套

from django.shortcuts import HttpResponse, render, redirect

(1)HttpResponse

作用:内部输入字符串 返回给浏览器

例如:

def index(request):
    # 业务逻辑代码
    return HttpResponse("hello world")

 

(2)render

作用:

(1)接受一个需要渲染的文件以及字典

(2)将数据填充进模板文件 返回给前端

例如:

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

PS:其前端接受取值 只能通过.的方式进行取值

 

(3)redirect

作用:接受一个url地址 跳转到另外一个地址

例如:

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

 

八:Web简易数据通讯过程

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!