1 HTTP协议
1.1 简介
- 超文本传输协议,是一种用于分布式、协作式和超媒体信息系统的应用层协议。
- 现今广泛使用的一个版本为–HTTP 1.1
- HTTP是一个客户端(用户)和服务端(网站)请求和应答的标准(TCP)。
- 通常由HTTP客户端发起一个请求,创建到一个服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口接收客户端请求。一旦收到请求,服务器就会向客户端返回一个状态,如“HTTP/1.1 200 OK”,以及返回的内容,如请求的人间、错误的信息或者其他信息
1.2 HTTP 工作原理
- HTTP协议采用请求/响应模型。
- 客户端向服务端发送一个请求报文,请求报文包含请求的方法、URL、协议版本、求情头部和请求数据。
- 服务器已一个状态行作为响应,响应的内容包括协议的版本、成功或错误代码、服务器信息、响应头部和相应数据。
- 以下是HTTP 请求、响应步骤:
- 客户端连接到WEB服务器。一个HTTP客户端,通常是浏览器,与WEB服务器的HTTP端口(默认是80)寄哪里一个TCP套接字连接。如 http://www.baidu.com
- 发送HTTP请求。通过TCP套接字,客户端向WEB服务器发送一个文本的请求报文。一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
- 服务器接收请求并返回HTTP响应。WEB服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4个部分组成。
- 释放连接TCP连接。若connection模式为close,则服务器主动关闭TCP连接,客户端被动关闭,释放TCP连接;若connection模式为keepalive,则该连接保持一段时间,在该时间内可以继续接收请求;
- 在客户端浏览器解析HTML内容。客户端浏览器先解析状态行,查看表明请求是否成功的状态码;然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符接;客户端浏览器读取响应数据HTML,根据HTML的语法进行格式化,在浏览器窗口中显示。
- 示例:在浏览器的地址栏键入URL,按下回车后会经历一下流程:
- 浏览器向DNS服务器请求解析该URL中的域名所对的IP地址;
- 解析出IP地址后,根据该IP地址和默认端口80,和服务器建立TCP连接;
- 浏览器发出读取文件(URL中域名后面部分对应的文件)的HTTP请求,该请求报文作为TCP三次握手的第三个报文的数据发送给服务器;
- 服务器作出响应,并把对应的 html 文本发送给浏览器;
- 释放TCP连接;
- 浏览器将 html 文本内容显示。
1.3 HTTP 协议特点
1.3.1 无状态保存
- HTTP是一种不保存状态的协议,即无状态协议。HTTP协议自身不对请求和响应之间的通讯状态进行保存。HTTP协议对发送的请求或响应都不做持久化处理。
- 使用HTTP协议,每当有新的请求发送时,就会有对应的新响应产生。协议本身并不保留之前一切的请求或响应报文的信息。这是为了更快地处理大量事务,确保协议的课伸缩性。
1.3.2 无连接(短连接)
-
无连接的含义是每次连接值处理一个请求。服务器处理完客户的请求,并受到客户的应答后,即断开连接。采用这种方式可以节省传输事件,并且提高并发性能。
-
早起的HTTP协议是一个请求响应之后就直接中断了。但是现在的HTTP协议1.1版本不是直接断开,而是等几秒,等待用户后续操作,如果用户在几秒内没有新的请求,那么就会断开连接。这样可以提高效率,减少短时间建立连接的次数。
1.4 HTTP请求方式
- GET:向指定的资源发出"显示"请求。使用GET方法应该只用在读取数据,而不应当被用于产生"副作用"的操作汇总,如Web Application。其中一个原因是GET可能被网络蜘蛛等随意访问。
- HEAD:于GET方法一样,都是向服务器发出制定个资源的请求。只不过服务器将不传回资源的本文部分。他的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中"关于该资源的信息"(元信息或元数据)
- POST:向指定资源提交数据,请求服务器进行处理(如:提交表单或上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。
- PUT:向指定资源位置上传其最新内容。
- DELETE:请求服务器删除Request-URI所有标识的资源。
- TRACE:回收服务器收到的请求,主要用于测试或诊断。
- OPTIONS:这个方法可以使用服务器传回该资源所支持的所有HTTP请求方法。用"*"来替代资源名称,Web服务器发送OPTIONS请求,可以测试服务器是否是正常运作。
- CONNECT:HTTP协议/1.1协议中预留给能将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接
- 注意事项
- 方法名称是区分大小写的。当某个请求所针对的资源不自持对应的请求方法的时候,服务器会返回状态码405,当服务器不认识或者不支持对应的请求方法时,返回状态码501。
- HTTP服务器至少应该实现GET和HEAD方法,方法都是可选的。当然,所有的方法支持的实现都应当匹配下述的方法各自的语义定义。除此之外,特定的HTTP服务器还能够拓展自定义的方法。
1.5 GET与POST请求
- GET请求提交的数据会放在URL后面,也就是请求行里面,以?分割URL和传输诗句,参数之间以&相连,如:EditBook?name=test1&id=123456;POST方法是把提交的数据放到HTTP请求体中。
- GET提交 的数据大小有限制(因为浏览器对URL的长度有限制),而POST提交的数据没有限制。
- GET与POST请求在服务端获取数据方式不同,就是我们自己在服务端请求数据的时候的方式不同。
1.6 HTTP状态码
- 所有HTTP响应的第一行都是状态行,依次是当前HTTP版本号,3位数字组成的状态代码,以及描述状态的短语,彼此有空格分隔。
- 状态代码的第一个数字代表当前响应的类型:
- 1xx 消息 —— 请求已被服务器接收,继续处理
- 2xx 成功 —— 请求一成功被服务器接收、理解并接受
- 3xx 重定向 —— 需要后续操作才能完成这一请求
- 4xx 请求错误 —— 请求含有词法错误或者无法被执行
- 5xx 服务器错误 —— 服务器在处理某个正确请求时发生错误
1.7 URL
-
超文本传输协议(HTTP)的统一资源定位符
-
将从因特网获取信息的五个基本元素包括在一个简单的地址中
- 传输协议
- 底层URL标记符号(为 // 固定不变)
- 访问资源需要的凭证信息(可省略)
- 服务器(通常为域名,有事为IP地址)
- 端口号(一数字方式表示,若为HTTP的默认值 :80 可省略)
- 路径(以 / 字符区分路径中的每一个目录名称)
- 查询(GET模式的窗体参数,以 ? 字符为起点,每个参数以 & 隔开,再已 = 分来参数名称与数据,通常以UTF8编码,避开字符冲突的问题)
- 片段(以 # 字符为起点)
-
示例:http://www.luffycity.com:80/news/index.html?id=250&page=1
- http:协议
- //:底层URL标记符号
- www.luffycity.com :服务器(域名)
- :80:服务器上默认的网络端口号,默认不显示
- /news/index.html:路径(URL直接定位到对应的资源)
- ?id=250&page=1:查询
1.8 HTTP请求格式(请求协议)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DggcF4Wu-1611811939149)(assets\HTTP请求格式(请求协议)].jpg)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-apgn1CBU-1611811939151)(assets\请求报文构成.png)]
1.9 HTTP响应格式(响应协议)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Hp7Wf4n-1611811939153)(assets\HTTP响应格式(响应协议).jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wLWLOpFK-1611811939155)(assets\响应报文的构成.png)]
2 web框架
1.1 本质
- 所有的web框架本质上就是一个socket 服务端,而用户的浏览器就是一个socket客户端,基于请求作出响应。
- 客户按照http协议的请求协议发送请求,服务端按照http协议的响应协议来响应请求。这就是web框架的本质。
1.2 自定义web框架
import socket
from threading import Thread
sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()
while True:
conn, addr = sk.accept()
from_b_msg = conn.recv(1024)
str_msg = from_b_msg.decode('utf-8')
conn.send(b'HTTP/1.1 200 ok \r\n\r\n')
def func(conn,path):
if path == '/':
with open('ceshi.html', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
else:
with open(i.strip('/'), 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
lst = ['/', '/test.css', '/test.js', '/1.jpg', '/1.icon']
path = str_msg.split(' ')[1]
for i in lst:
if path == i:
Thread(target=func, args=(conn, path)).start()
sk.close()
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<link href="前端工具/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="test.css">
<link rel="icon" href="1.icon">
</head>
<body>
<h1 id="h1">欢迎来到德莱联盟</h1>
<img src="1.jpg" alt="" width="340" height="210">
</body>
<script src="前端工具/jQuery.js"></script>
<script src="前端工具/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
<script src="test.js"></script>
</html>
h1{
width: 340px;
background-color: black;
color: white;
}
alert('这里是祖安')
3 Django 项目的创建及配置
3.1 通过命令创建Django项目
- 进入目标文件夹
- 创建项目:django-admin startproject 项目名称
- 进入项目目录
- 创建应用:python manage.py startapp 应用名称
- python manage.py runserver ip:端口 默认是127.0.0.1:8000
# 通过指令创建的应用,必须在项目中的settings.py文件中的INSTALL_APP列表最后加上应用名称
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01' # 添加应用名称
]
# 现阶段在获取post请求数据时,需在settings.py文件中的MIDDLEWARE列表中注销配置
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware', # 此项需注销
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
3.2 Django项目配置
3.2.1 基本配置
-
项目同名文件夹下的 settings.py 文件
-
在 INSTALLED_APPS 列表后面添加新创建的app名称,如果是用pycharm创建的项目,第一个APP名称无须添加,后面的app名称需要通过命令创建并手动添加至此
-
在 TEMPLATES 类表的 ‘DIRS’: [BASE_DIR, ‘templates’] 键值对配置。此项为存放拼接存放 html 等文件的路径,templates为pycharm默认创建,可以根据自身需求修改
-
在 DATABASES 字典下配置(数据库相关配置)
- 将Django连接的数据库改为mysql:‘ENGINE’: ‘django.db.backends.mysql’
- ‘NAME’ 为连接数据库的名字
- 新增 ‘HOST’(数据库地址),‘PORT’(端口号3306),‘USER’(用户名),‘PASSWORD’(密码)的键值对
-
配置静态文件配置
- 在项目目录下新建静态文件存放目录
- 在settings 文件中配置
# settings.py 文件末尾处新增 STATIC_URL = '/static/' # 别名 STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'statics') ] # (statics为新建存放静态文件的文件夹,可随意命名)
- 在页面中引用
<!-- 前端模板部分引用 --> <!-- 方式一 --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/xx.css"> <!--此处写的是别名,不是目录名--> </head> <body> <img src="/static/xx.jpg" alt=""> </body> <script src="/static/xx.js"></script> </html> <!-- 方式二 --> {% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="{% static 'xx.css' %}"> </head> <body> <img src="{% static 'xx.jpg' %}" alt=""> </body> <script src="{% static 'xx.js' %}"></script> </html>
-
-
项目同名文件夹下的 _init_.py 文件(数据库相关配置)
- 修改 Django 连接数据库的方式
import pymysql pymysql.install_as_MySQLdb()
3.2.4 通过外部脚本文件,操作Django项目
- 在项目文件夹下新建脚本文件
- 方式如下,顺序不可改变
# 脚本文件配置
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day08_ject_cookie.settings") # manage.py 文件中的第一句话
import django
django.setup()
from app01 import models
# 操作语句
3.2.5 打印ORM转换过程中的SQL语句
-
方式一:以日志的形式输出
# 在项目同名文件夹下的 settings.py 文件中配置 # 在 DATABASES 字典下配置如下 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
-
方式二
from django.db import connection #通过这种方式也能查看执行的sql语句 print(connection.queries)
3.2.6 在 Django 中执行原生 SQL 语句
-
方式一
from django.db import connection cursor = connection.cursor() cursor.execute('select * from app01_book') print(cursor.fetchall())
-
方式二
obj_author = models.Author.objects.raw('select * from app01_author') # 只限于本表操作
3.3 简单的登录界面
- django-admin startproject 项目名称
- cd 项目所在文件夹
- python manage.py startapp app01
- 在settings.py文件中的INSTALLED_APPS列表配置APP目录
- 注释settings.py文件中MIDDLEWARE类表中的django.middleware.csrf.CsrfViewMiddleware,
# urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
# from app名 improt 方法
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login)
]
# views.py
from django.shortcuts import render,HttpResponse
# Create your views here.
def login(request):
if request.method == 'GET': # 获取请求方式
return render(request, 'login.html') # reder(request, 'html文件') 返回页面
else:
if request.POST.get('username') == '啦啦啦' and request.POST.get('pwd') == '666':
return HttpResponse('成功')
else:
return HttpResponse('失败') # HttpResponse 返回字符串
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="" method="post">
<!--不写默认在当前的页面提交-->
<!--写相对路径,系统会默认补全-->
用户名:<input type="text" name="username">
密码:<input type="password" name="pwd">
<input type="submit">
</form>
</body>
</html>
3.4 其他配置
3.4.1 组件
- 将一套完整的功能封装成模块,以便引用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% include '组件路径/组件名' %} <!-- 引用组件 -->
</body>
</html>
3.4.2 取消自动加斜杆
- Django 在接受请求,路由分发时,会将没有斜杆的路径进行匹配
- Django 会向浏览器发起重定向请求,在路径后面加斜杆,重新请求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ksNcW2eF-1611811939156)(assets\带斜杆重定向.png)]
- 取消自动添加斜杆(注意清除缓存再做尝试)
# 在项目同名文件夹下的 setting.py 文件中手动添加
APPEND_SLASH = False
# APPEND_SLASH = True # 默认是开启状态
3.4.3 通过现有数据库,生成 models.py 文件中的类
- 通过终端,切换至项目所在的文件夹
- 在终端中输入:python manage.py inspectdb > app01/models.py
3.4.4 到处项目中所需所有模块及版本号
- 通过终端,切换至项目所在的文件夹
- pip3 freeze > requirement.txt(默认叫requirement)
4 URL 路由系统
4.1 路由分组
# 与项目同名文件夹下的 urls.py 文件
urlpatterns = [
url(r'^book/(?P<year>\d+)/',views.book), # 有名分组
url(r'^books/(\d+)/(\d+)',views.book) # 无名分组
]
4.2 URL路径别名及反向解析
4.2.1 URL路径起别名
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.home),
url(r'^other/(\d+)/', views.other, name='other'), # 无名分组
url(r'^person/(?P<year>\d+)/', views.person, name='person'), # 有名分组
url(r'^lalala/', views.lalala, name='lalala'), # 无分组
]
4.2.2 URL路径反向解析(后端视图部分)
from django.shortcuts import render,redirect
from django.shortcuts import reverse # 需引入模块完成路径反向解析
# Create your views here.
def home(request):
return redirect(reverse('other', args=(1,))) # 无名分组路径反向解析,必须带reverse
def other(request, n):
return redirect(reverse('person', kwargs={
'year':n})) # 有名分组路径反向解析,必须带reverse
def person(request, year):
return redirect('lalala') # 无分组路径反向解析,可以不带reverse
def lalala(request):
return render(request, 'lalala.html')
4.2.3 URL路径反向解析(前端模板部分)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="{% url 'home' %}"> <!-- 无分组 -->
<h1>Welcome to home</h1>
</a>
<a href="{% url 'other' 1 %}"> <!-- 有名分组和无名分组均这样写 -->
<h1>滚蛋</h1>
</a>
</ body>
</html>
4.3 URL路径分发和命名空间
4.3.1 URL路径分发
- 在各自app文件夹下创建urls.py文件
- 在各自的urls.py文件下配置路径
- 在项目同名文件夹下的urls.py文件下进行路径分发配置
- 在各自应用文件夹下调用路径
# app01/urls.py 文件
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^index/', views.index, name='index') # 取别名
]
# app02/urls.py 文件
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'^index/', views.index, name='index') # 取别名
]
# 项目同名文件夹下的 urls.py 文件
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include('app01.urls')),
url(r'^app02/', include('app02.urls')),
]
# app01/views.py
from django.shortcuts import render,HttpResponse,reverse