一: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没有变动
(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>
wsgiref模块的详细分析
流程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>')
redirect
def home(request):
return redirect("http://www.mzitu.com/")
render
"""
render方法可接收三个参数:
一是request参数;
二是待渲染的html模板文件;
三是保存具体数据的字典参数。
"""
def hello(request):
return render(request,'hello.html')