一:Django框架初识

http/https/websocket

# http协议:超文本传输协议,具有以下特性:
(1)基于request和response;
(2)基于TCP/IP并作用于应用层之上的协议;
(3)无状态,不保存用的状态信息;
(4)无链接/短链接
http协议的数据传输是明文,默认端口80
# https协议:是以安全为目的的安全通道,即http+ssl,传输的数据是加密的(通过ssl完成加密),默认端口443
# websocket:一种基于TCP的新型网络协议

http数据格式

请求首行
请求头
\r\n
请求体
"""
GET /index HTTP/1.1\r\n
Host: 182.xx.xx.34:9090\r\n
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Purpose: prefetch
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9\r\n
\r\n

"""

一个web框架的简单雏形

import socket
from threading import Thread

IP_ADDRESS = ('0.0.0.0', 9090)
BUF_SIZE = 8096


class MyServer(object):
    def __init__(self, ip_address):
        self.ip_address = ip_address
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def bind(self):
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server.bind(self.ip_address)

    def listen(self):
        self.server.listen(5)

    def accept(self):
        return self.server.accept()

    @staticmethod
    def communicate(conn, addr):
        print(f'收到[{addr[0]}:{addr[1]}]的链接请求')
        while True:
            data = conn.recv(BUF_SIZE).decode('utf-8')
            conn.send(b'HTTP/1.1 200 OK\r\nContent_Type: text/html; charset=utf-8\r\n\r\n')
            visit_path = data.split(' ')[1]
            print(visit_path)
            print(data.split(' '))
            if visit_path == '/index':
                res = 'hello, i am index!'
            elif visit_path == '/home':
                res = 'hello, i am home'
            else:
                res = '404 , not found page'
            conn.send(bytes(res, encoding='utf-8'))
            conn.close()

    def run(self):
        self.bind()
        self.listen()
        while True:
            conn, addr = self.accept()
            t = Thread(target=self.communicate, args=(conn, addr))
            t.start()


if __name__ == '__main__':
    s = MyServer(IP_ADDRESS)
    s.run()

上述示例中传输的是普通的字符串,我们也可以传输带有html标签的文本,甚至是文件,随着功能的扩展,我们需要将都写在一个文件中显然是不合适的,我们将文件进行拆分成,ulrs.py,views.py,mysocket.py

urls.py: 路由与视图的对应关系
views.py:视图函数
mysocket.py: 处理socket请求

urls.py

"""路由与视图的一一对应关系"""
from views import *

urls = [
    ('/index',index),
    ('/home',home),
]

views.py

"""处理业务逻辑"""
def index():
    res = '<h1>hello world</h1>'
    return res


def home():
    res = '<a href="http://www.mzitu.com/" target="_blank">look</a>'
    return res

mysocket.py

import socket
from threading import Thread
from urls import urls
from views import *

IP_ADDRESS = ('0.0.0.0', 9090)
BUF_SIZE = 8096


class MyServer(object):
    def __init__(self, ip_address):
        self.ip_address = ip_address
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def bind(self):
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server.bind(self.ip_address)

    def listen(self):
        self.server.listen(5)

    def accept(self):
        return self.server.accept()

    @staticmethod
    def communicate(conn, addr):
        print(f'收到[{addr[0]}:{addr[1]}]的链接请求')
        while True:
            data = conn.recv(BUF_SIZE).decode('utf-8')
            conn.send(b'HTTP/1.1 200 OK\r\nContent_Type: text/html; charset=utf-8\r\n\r\n')
            visit_path = data.split(' ')[1]
            func = None
            for url in urls:
                if url[0] == visit_path:
                    func = url[1]
                    break
            if func:
                res = func()
            else:
                res = '404 not found page'
            conn.send(bytes(res, encoding='utf-8'))
            conn.close()

    def run(self):
        self.bind()
        self.listen()
        while True:
            conn, addr = self.accept()
            t = Thread(target=self.communicate, args=(conn, addr))
            t.start()


if __name__ == '__main__':
    s = MyServer(IP_ADDRESS)
    s.run()

借助于wsgiref模块来实现

静态HTML文件的显示

urls.py

from views import*

urls = [
    ('/index',index),
    ('/home',home),
]

views.py

def index(environ):
    pass

def home(environ):
    pass

text1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="content-type" charset="UTF-8">
    <title>test1</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <style>
        a{
            text-decoration: none;
        }
    </style>
</head>
<body>
<a href="http://www.mzitu.com/" target="_blank">福利链接1</a>
</body>
</html>

text2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="content-type" charset="UTF-8">
    <title>test2</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <style>
        a{
            text-decoration: none;
        }
    </style>
</head>
<body>
<a href="http://www.baidu.com" target="_blank">福利链接2</a>
</body>
</html>

myserver.py

from wsgiref.simple_server import make_server
from views import *
from urls import urls


def run(environ, start_response):
    """
    environ:请求相关的所有数据,一个大字典
    start_response:响应相关的所有数据
    return:返回给浏览器的数据
    """
    start_response('200 OK',[('Content_Type','text/html'),])
    func = None
    for url in urls:
        if url[0] == environ.get('PATH_INFO'):
            func = url[1]
            break
    if func:
        res = func(environ)
    else:
        res = '404,not page found!'
    return [bytes(res,encoding='utf-8'),]



if __name__ == '__main__':
    s = make_server('0.0.0.0', 9090, run)
    s.serve_forever()

动态html文件的显示

(1)从后端返回一个字典给用户

urls.py

from views import *

urls = [
    ('/home',home),
]

views.py

from jinja2 import Template

def home(environ):
    user_info = {'name': 'jason', 'age': 18, 'hobby': 'dbj'}
    with open('active1.html', mode='r', encoding='utf-8') as f:
        data = f.read()
    tmp = Template(data)
    res = tmp.render(user=user_info)
    return res

active1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="content-type" charset="UTF-8">
    <title>active1</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
{{ user }}  /*获取user字典*/
{{ user.get('name')}} /*获取属性name的值*/
{{ user['age']}} /*获取属性age的值*/
{{ user.hobby }} /*获取属性hobby的值*/
</body>
</html>

myserver.py没有变动

img

(2)后端从数据库拿到数据返回给前端进行展示

urls.py

from views import *

urls = [
    ('/index',home),
]

views.py

from jinja2 import Template //模板语法
import pymysql


def index(environ):
    conn = pymysql.connect(
        host='0.0.0.0',
        port=3306,
        user='root',
        password='123456',
        database='day59',
        charset='utf8',
        autocommit=True,
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    sql = "SELECT * FROM user"
    affect_rows = cursor.execute(sql)
    data_list = cursor.fetchall()
    with open('active1.html', mode='r', encoding='utf-8') as f:
        data = f.read()
    tmp = Template(data)
    res = tmp.render(user_list=data_list)
    return res

active1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="content-type" charset="UTF-8">
    <title>active1</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/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">
            <h1 class="text-center">用户数据</h1>
            <table class="table table-hover table-striped">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>NAME</th>
                        <th>AGE</th>
                        <th>HOBBY</th>
                    </tr>
                </thead>
                <tbody>
                    {% for user_dict in user_list %}
                    <tr>
                        <td>{{user_dict.id}}</td>
                        <td>{{user_dict.name}}</td>
                        <td>{{user_dict.age}}</td>
                        <td>{{user_dict.hobby}}</td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>

img

wsgiref模块的详细分析

img

流程1:浏览器请求、wsgiref解析封装数据、urls路由分发、views视图逻辑处理、返回模版html页面、wsgiref打包封装、交给浏览器展示数据。

流程2:浏览器请求、wsgiref解析封装数据、urls路由分发、views视图逻辑处理、调用数据库数据、渲染到模版html页面上、返回模版html页面、wsgiref打包封装、交给浏览器展示数据。

wsgiref其实给我们干了两件事情:

(1)按照http请求协议解析数据
(2)按照http响应协议来组织数据

python的三大主流框架介绍

(1)Django框架

python最出名的web框架,它最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构、以及全功能的管理后台。

特点:大而全,有时候过于笨重

(2)FLASK

一个用python写的轻量级web框架,

特点:自带功能特别少,第三模块特别多,依赖性严重(第三方模块)

(3)tornado

特点:异步非阻塞,支持高并发

我们将一个框架分为以下3个模块:

"""
A:socket部分(用于解析http请求,组织相关的数据按照http格式响应)
B: 路由与视图函数的一一对应关系
C:模板语法
"""

三种框架的对比

A 部分 B部分 C部分
Django 用的wsgiref模块 用的自己的 用的自己的
FLASK werkzeug(内部还是 wsgiref模块) 用的自己的 jinja2
tornado 用的自己写的 用的自己写的 用的自己写的

Django框架的安装

Linux安装

pip install django==1.11.29

创建一个django项目

# 使用django-admin startproject xx项目名
[root@alisurpass project]# django-admin startproject wpsite

# 创建一个应用 python manage.py startapp app名称
[root@alisurpass wpsite]# python manage.py startapp app01

# 创建静态文件夹static和HTML存放文件夹templates
[root@alisurpass wpsite]# mkdir -p static templates

# 修改项目中的配置文件
(1)注册app

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',  #全写,可以简写‘app01’
]

(2)添加访问的主机
ALLOWED_HOSTS = ['*'] #使得所有主机度可以访问,为了防止非法入侵,这里可以设置访问的IP 如['182.92.59.34','127.0.0.1']

(3)TEMPLATES里面添加模板的path
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], #添加path
        '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',
            ],
        },
    },
]

(4) 添加静态文件路径
STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'static'),
)

然后我们就可以启动django项目了

[root@alisurpass wpsite]# python manage.py runserver 0.0.0.0:9090

目录如下

.
├── app01
│   ├── admin.py    #django后台管理
│   ├── apps.py     #注册使用
│   ├── __init__.py
│   ├── migrations  #数据库迁移记录
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-38.pyc
│   ├── models.py   #数据库相关 模型类(orm)
│   ├── __pycache__
│   │   ├── admin.cpython-38.pyc
│   │   ├── apps.cpython-38.pyc
│   │   ├── __init__.cpython-38.pyc
│   │   └── models.cpython-38.pyc
│   ├── tests.py    #测试文件
│   └── views.py    #视图函数(视图层)
├── db.sqlite3
├── manage.py        #Django的入口文件
├── static
├── templates
└── wpsite
    ├── __init__.py
    ├── __pycache__
    │   ├── __init__.cpython-38.pyc
    │   ├── settings.cpython-38.pyc
    │   ├── urls.cpython-38.pyc
    │   └── wsgi.cpython-38.pyc
    ├── settings.py    #配置文件
    ├── urls.py        #路由与视图函数的一一对应关系
    └── wsgi.py        #wsgiref模块

8 directories, 22 files

Django三大核心命令

httpResponse

def index(request):
    #业务逻辑代码
    return HttpResponse('<a href="http://www.mzitu.com/" target="_blank">hello</a>')

img

redirect

def home(request):
    return redirect("http://www.mzitu.com/")

img

render

"""
render方法可接收三个参数:
一是request参数;
二是待渲染的html模板文件;
三是保存具体数据的字典参数。
"""
def hello(request):
    return render(request,'hello.html')

img

posted @ 2020-11-08 16:17  为了等  阅读(81)  评论(0编辑  收藏  举报