啥是DNS
DNS是域名解析系统,当我们通过浏览器发送如“ baidu.com” 时会先发送给本地DNS,没有找到的话会再发送到根服务器,世界上一共有13台根服务器,
10台在美国,两台在欧洲,一台在日本。这不是重点,根服务器会拿到我们发的请求时,会解析后面的.com部分,发送信息给
管理.com的顶级服务器中去查找,再通过.com顶级服务器找到管理baidu.com的权威服务器,返回一个ip和端口给本地DNS,本地会记录下来IP地址并访问www.baidui.com。
DNS就是记录着域名和ip的对应关系
HTTP协议
http协议向服务器请求时使用的 由两个部分组成的,请求头和请求体,请求头和请求体用 分隔开,请求头中包含请求方式,方式选择上有两种,客户端不往服务器传数据可以使用,get请求,有数据传输的时候可以使用post请求。还包含请求的主机名,本次的连接状态,在http1.1版本下默认使用的是长链接的形式,最重要的是user-Agent 其中包含了我们请求的主要信息。
# b'GET / HTTP/1.1 请求方式,请求页面和协议版本号 # Host: 127.0.0.1:8001 被请求的主机名 # Connection: keep-alive 链接状态---本次长连接 # Cache-Control: max-age=0 缓存失效 # Upgrade-Insecure-Requests: 1 # User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 # Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 # Referer: https://www.baidu.com/s?ie=UTF-8&wd=127.0.0.1%EF%BC%9A8001 # Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 '
请求体就是我们输入的内容。
请求和相应是相对应的,所以服务器也会有响应头和响应体,最基础的要包含http和版本号,状态码,是200的话再来一个ok,讲究一点在指定一个字符编码。
(b'HTTP/1.1 200 ok Content-Type: text/html;charset=utf8 '
在http协议下我们不指定端口时默认使用的是80端口,在https协议下默认的端口是443
相应的状态码:
2XX: 200 (ok)
3XX: 302 304
4XX: 404(not found) 403(forbidden 禁止访问)
5XX: 500 (服务端代码错误) 502 (网关错误 bad gateway)
Django前菜:手撸简易web框架
可以自己写出一个socket服务端,指定我们自己主机的ip和端口通过浏览器向服务器发起请求通信完成请求和回应,
原理是在服务端解析客户端,得到客户端发起请求的方式,请求的页面。
在服务器方面我们可以模拟Django中的路由系统建立字符串和函数的对应关系。做一个任务的分发,当客户端请求的页面在
我们所设定的列表中时,就调用向对应的函数,处理数据并返回处理结果给客户端。
def f1(): return 'this is xxx' def f2(): return 'this is ooo' def f3(): pass router = [ ('/xxx',f1), ('/ooo',f2), ('/three',f3) ]
服务器主要逻辑,及部分实现的功能代码:
import datetime import socket import time import pymysql server = socket.socket() server.bind(('127.0.0.1',8001)) server.listen(5) def f1(): return 'this is xxx' def f2(): return 'this is ooo' def f3(): pass router = [ ('/xxx',f1), ('/ooo',f2), ('/three',f3) ] while True: print('监听8001端口') client,addr = server.accept() #接收到客户端发来的数据 data = client.recv(1024) print(data) #j将接收到二进制数据转为字符串形式,进行切分找到我们想要的响应头中的内容 res = str(data,encoding='utf-8') #想要的响应头部分内容通过打印在响应头的在切分所得列表的0号位 request_list = res.split(' ')[0] #再将取得的数据按空格切分 frist_list = request_list.split(' ')
['GET', '/xxx', 'HTTP/1.1']# frist_list打印结果
client.send(b'HTTP/1.1 200 ok Content-Type: text/html;charset=utf8 ') funcname = None for item in router: if frist_list[1] == item[0]: funcname = item[1] if funcname: res = funcname() client.send(bytes(res,encoding='utf-8')) else: client.send(bytes('404 not found',encoding='utf-8')) client.close()
客户端发来请求的打印结果:
# b'GET / HTTP/1.1 # Host: 127.0.0.1:8001 # Connection: keep-alive # Cache-Control: max-age=0 # Upgrade-Insecure-Requests: 1 # User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 # Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 # Referer: https://www.baidu.com/s?ie=UTF-8&wd=127.0.0.1%EF%BC%9A8001 # Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 '
模板渲染
模板渲染可以自己定制规则,也可以使用第三方模块,
将数据库中的数据查找出后,可以结合html来形成渲染模板将结果融合在一起。
我们先将数据库中的数据通过列表套字典的形式取出,我们在我们想要渲染的html页面中,用一个占位符去先代替,
我们想要渲染进去的数据,再打开html文件后,读出数据后。我们将数据拼接成表格的形式,通过替换来将本来html文件中
的占位符替换掉这样html中的数据就是我们数据库的数据,并且数据是动态的。
import pymysql conn = pymysql.connect(host='127.0.0.1', user='root', password='123', db='db1', charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = "select id, name, depart_id from userinfo" cursor.execute(sql) res = cursor.fetchall() ### 模板渲染 ### 需要将html代码和mysql结果融合 res_list = [] for user in res: res_str = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" % (user['id'], user['name'], user['depart_id']) res_list.append(res_str) s = "".join(res_list) fp = open('content.html', 'r', encoding='utf-8') data = fp.read() data = data.replace("@@content@@", s) return bytes(data, encoding='utf-8')
第三方模块渲染
导入第三方模块
from jinja2 import Template
使用template去找到html文件中的占位符,将它替换成我们自己拼接好的数据。在html中去对数据进行取值遍历
在添加数据时要使用{{}}来包裹,对值进行循环遍历的时候要用{% for user in res%}进行包裹,对字典取值可以直接通过点的方法
来取值。
import pymysql conn = pymysql.connect(host='127.0.0.1', user='root', password='123', db='db1', charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = "select id, name, depart_id from userinfo" cursor.execute(sql) users = cursor.fetchall() print(users) ''' [ {'id': 1, 'name': 'root1', 'depart_id': 1}, {'id': 4, 'name': 'root2', 'depart_id': 3}, {'id': 5, 'name': 'root3', 'depart_id': 5}, {'id': 6, 'name': 'root4', 'depart_id': 1}, {'id': 7, 'name': 'root5', 'depart_id': 3} ] ''' ### 模板渲染 ### pip3 install jinja2 fp = open('content-jinji2.html', 'r', encoding='utf-8') data = fp.read() from jinja2 import Template template = Template(data) data = template.render(users = users) return bytes(data, encoding='utf-8')
安装Django
在cmd终端中安装方法:pip3 install Django==1.11.10
Django帮我们封装了,socket,我们不用自己去获取客户端的请求,
目录介绍:
mysite:
mysite:
settings.py : 用户自定义的各种配置
urls.py : 路由文件
wsgi.py : 启动socket服务端的 文件
mange.py: 管理文件 python mange.py 各种命令
创建完成以后我们要第一时间去配置一些静态文件路径,pycharm已经给我们配置好了动态文件路径
还要注释掉 MIDDLEWARE 中间的一条配置文件:#'django.middleware.csrf.CsrfViewMiddleware',
静态文件配置:
STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), (逗号不能少) )
书写uri和函数的对应关系:
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', login), url(r'^user_table/', user_table), ]
创建Django项目: 在pycharm中在新建项目中点击Django即可
函数是我们书写业务逻辑的地方。
案例:实现简单的登录:
import pymysql from django.conf.urls import url from django.contrib import admin from django.http import HttpResponse from django.shortcuts import render,HttpResponse,redirect def py(): conn = pymysql.connect(host='localhost', user='root', password='123', database='db2', charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = 'select * from login' cursor.execute(sql) conn.commit() res = cursor.fetchall() return res def login(request): if request.method == "GET": return render(request,'login.html') elif request.method == 'POST': name = request.POST.get('username') pwd = request.POST.get('password') res = py() for user in res: if user['name'] == name and user['pwd'] == pwd: return redirect('/user_table') else: return render(request, 'login.html',{ 'info':'登录失败' }) def user_table(request): res = py() return render(request,'user_table.html',locals()) urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', login), url(r'^user_table/', user_table), ]