django web开发实例,django框架百度百科
Web框架的本质可以这样理解:所有的Web应用本质上都是一个socket服务器,用户的浏览器就是一个socket客户端。这样我们就可以自己实现Web框架了。
半成品定制web框架
导入插座
sk=socket.socket()
sk.bind((127.0.0.1 ,80))
sk.listen()
虽然正确:
conn,addr=sk.accept()
data=conn.recv(8096)
连接发送(b 确定)
conn.close()
可以说Web服务本质上是在这十几行代码的基础上扩展的。这个代码是他们的祖先。
用户的浏览器一输入URL,就会向服务器发送数据。浏览器会发送什么数据?怎么发?谁来决定这个?你的网站按照这个规定,他的网站按照他的规定。这个互联网还能玩吗?
所以一定要有一个统一的规则,这样你收发消息的时候才能有格式依据,不能随便写。
这个规则就是HTTP协议。以后无论是浏览器发送请求消息,还是服务器回复响应消息,都要遵循这个规则。
HTTP协议主要规定了客户端和服务器之间的通信格式。HTTP协议如何指定消息格式?
让我们首先打印出我们在服务器端收到的消息是什么。
导入插座
sk=socket.socket()
sk.bind((127.0.0.1 ,80))
sk.listen()
虽然正确:
conn,addr=sk.accept()
data=conn.recv(8096)
Print(data) #从浏览器打印消息。
连接发送(b 确定)
conn.close()
输出:
b get/HTTP/1.1 \ r \ n host:127 . 0 . 0 . 1:8080 \ r \ n connection:keep-alive \ r \ n upgrade-unsecured-Requests:1 \ r \ n user-Agent:Mozilla/5.0(Windows NT 10.0;Win64x64) AppleWebKit/537.36 (KHTML,像壁虎一样)Chrome/64 . 0 . 3282 . 186 Safari/537.36 \ r \ n cept:text/html,application/xhtml xml,application/XML;q=0.9,image/webp,image/apng,*/*;q=0.8 \ r \ nDNT:1 \ r \ n cept-Encoding:gzip,deflate,br \ r \ n cept-Language:zh-CN,zh。 q=0.9 \ r \ ncoookie:csrftoken=rkbxh 1d 3m 97 iz 03 rpbojx 1 br 6 mhhudhyx 5 pszuxxg 3 boewh 1 lxfpgogwn 93 zh 3 zv \ r \ n \ r \ n
然后,我们来看看我们在官网访问博客园时浏览器收到的响应消息。
可以在浏览器调试窗口的网络选项卡中看到响应信息。
点击【查看源代码】,出现下图:
我们发现发送和接收的消息需要遵循一定的格式,所以我们需要了解这里的HTTP协议。
HTTP协议简介
HTTP协议发送和接收消息的格式要求
每个HTTP请求和响应遵循相同的格式,一个HTTP包含两个部分:头和主体,其中主体是可选的。HTTP响应的头中有一个Content-Type来指示响应的内容格式。Text/HTML表示HTML网页。
http请求的格式:
HTTP响应的格式:
经过上面的补充学习,我们知道,为了让自己的web服务器正确,必须让自己的Web服务器在回复客户端时,按照HTTP协议的规则添加响应状态行,这样才能实现一个严肃的Web框架。
导入插座
sock=socket.socket(socket。AF_INET,socket。袜子_流)
sock.bind((127.0.0.1 ,8000))
sock.listen()
虽然正确:
conn,addr=sock.accept()
data=conn.recv(8096)
#在回复消息中添加响应状态行。
conn . send(b http/1.1 200 OK \ r \ n \ r \ n )
连接发送(b 确定)
conn.close()
我们只是通过十几行代码演示了web框架的本质。
接下来,让我们继续改进我们的自定义web框架!
根据不同的路径返回不同的内容。结束了吗?如何让我们的Web服务根据用户请求的不同URL返回不同的内容?
这是小菜一碟。我们可以从与请求相关的数据中获取请求URL的路径,然后用路径进行判断。
根据URL中不同的路径,返回不同的内容。
导入插座
sk=socket.socket()
Sk.bind((127.0.0.1 ,8080)) #绑定IP和端口
Sk.listen() #听
而1:
#等待连接
conn,add=sk.accept()
Data=conn.recv(8096) #接收来自客户端的消息
#从数据中获取路径
Data=str (data,encoding= UTF8) #将接收到的字节类型数据转换为字符串。
#拆分者\r\n
data1=data.split(\r\n)[0]
Url=data1.split()[1] # url是我们从浏览器发送的消息中分离出来的访问路径。
conn . send(b HTTP/1.1 200 ok \ r \ n \ r \ n )#因为应该遵循HTTP协议,所以应该在回复消息中添加状态行。
#根据不同的路径返回不同的内容
如果url==/index/:
响应=b“指数”
elif url==/home/:
响应=b“家”
否则:
response=b 找不到404!
conn.send(响应)
conn.close()
根据不同的路径返回不同的内容——函数版本上面的代码解决了不同的URL路径返回不同内容的需求。
但是问题又来了。如果有很多很多路径要判断呢?if判断一定要一个一个写吗?不,当然,我们有更聪明的方法。
在URL-function版本中根据不同的路径返回不同的内容
导入插座
sk=socket.socket()
Sk.bind((127.0.0.1 ,8080)) #绑定IP和端口
Sk.listen() #听
#将返回的不同内容部分封装到函数中
定义索引(url):
S=这是第{}页!。格式(url)
返回字节(s,编码=utf8 )
定义主页(url):
S=这是第{}页!。格式(url)
返回字节(s,编码=utf8 )
而1:
#等待连接
conn,add=sk.accept()
Data=conn.recv(8096) #接收来自客户端的消息
#从数据中获取路径
Data=str (data,encoding= UTF8) #将接收到的字节类型数据转换为字符串。
#拆分者\r\n
data1=data.split(\r\n)[0]
Url=data1.split()[1] # url是我们从浏览器发送的消息中分离出来的访问路径。
conn . send(b HTTP/1.1 200 ok \ r \ n \ r \ n )#因为应该遵循HTTP协议,所以应该在回复消息中添加状态行。
#根据不同的路径返回不同的内容,response是具体的响应体。
如果url==/index/:
响应=索引(url)
elif url==/home/:
响应=主页(url)
否则:
response=b 找不到404!
conn.send(响应)
conn.close()
根据不同的路径,返回不同的内容——函数的高级版看起来上面的代码还是要一个一个写if判断。我该怎么办?我们还有办法!只要思想不滑坡,方法总比问题多!)
在URL-function高级版中根据不同的路径返回不同的内容
导入插座
sk=socket.socket()
Sk.bind((127.0.0.1 ,8080)) #绑定IP和端口
Sk.listen() #听
#将返回的不同内容部分封装到函数中
定义索引(url):
S=这是第{}页!。格式(url)
返回字节(s,编码=utf8 )
定义主页(url):
S=这是第{}页!。格式(url)
返回字节(s,编码=utf8 )
#定义url和要执行的实际功能之间的对应关系
list1=[
(/index/,index),
(/home/,home),
]
而1:
#等待连接
conn,add=sk.accept()
Data=conn.recv(8096) #接收来自客户端的消息
#从数据中获取路径
Data=str (data,encoding= UTF8) #将接收到的字节类型数据转换为字符串。
#拆分者\r\n
data1=data.split(\r\n)[0]
Url=data1.split()[1] # url是我们从浏览器发送的消息中分离出来的访问路径。
conn . send(b HTTP/1.1 200 ok \ r \ n \ r \ n )#因为应该遵循HTTP协议,所以应该在回复消息中添加状态行。
#根据不同的路径返回不同的内容
Func=None #定义一个保存要执行的函数名称的变量。
对于列表1中的I:
if i[0]==url:
func=i[1]
破裂
if func:
response=func(url)
否则:
response=b 找不到404!
#返回特定的响应消息
conn.send(响应)
conn.close()
返回的特定HTML文件完美解决了不同URL返回不同内容的问题。但我不想只返回几个字符串。我想向浏览器返回完整的HTML内容。我该怎么办?
没问题,不管是什么,最后都转换成字节数据发出去。我们可以打开HTML文件,读出它内部的二进制数据,然后发送给浏览器。
在URL-function高级版中根据不同的路径返回不同的内容
返回到单独的HTML页面
导入插座
sk=socket.socket()
Sk.bind((127.0.0.1 ,8080)) #绑定IP和端口
Sk.listen() #听
#将返回的不同内容部分封装到函数中
定义索引(url):
#阅读index.html页面的内容
用open(index.html , r ,encoding=utf8 )作为f:
s=f.read()
#返回字节数据
返回字节(s,编码=utf8 )
定义主页(url):
用open(home.html , r ,encoding=utf8 )作为f:
s=f.read()
返回字节(s,编码=utf8 )
#定义url和要执行的实际功能之间的对应关系
list1=[
(/index/,index),
(/home/,home),
]
而1:
#等待连接
conn,add=sk.accept()
Data=conn.recv(8096) #接收来自客户端的消息
#从数据中获取路径
Data=str (data,encoding= UTF8) #将接收到的字节类型数据转换为字符串。
#拆分者\r\n
data1=data.split(\r\n)[0]
Url=data1.split()[1] # url是我们从浏览器发送的消息中分离出来的访问路径。
conn . send(b HTTP/1.1 200 ok \ r \ n \ r \ n )#因为应该遵循HTTP协议,所以应该在回复消息中添加状态行。
#根据不同的路径返回不同的内容
Func=None #定义一个保存要执行的函数名称的变量。
对于列表1中的I:
if i[0]==url:
func=i[1]
破裂
if func:
response=func(url)
否则:
response=b 找不到404!
#返回特定的响应消息
conn.send(响应)
conn.close()
使网页动态化。这个网页可以显示,但是都是静态的。页面内容不会改变。我想要的是一个动态的网站。
没问题,我也能解决。我选择使用字符串替换来满足这个需求。(这里使用时间戳来模拟动态数据)
在URL-function高级版中根据不同的路径返回不同的内容
返回HTML页面
使网页动态化。
导入插座
导入时间
sk=socket.socket()
Sk.bind((127.0.0.1 ,8080)) #绑定IP和端口
Sk.listen() #听
#将返回的不同内容部分封装到函数中
定义索引(url):
用open(index.html , r ,encoding=utf8 )作为f:
s=f.read()
now=str(time.time())
S=s.replace(@@oo@@ ,现在)#定义网页中的特殊符号,用动态数据替换预先定义的特殊符号。
返回字节(s,编码=utf8 )
定义主页(url):
用open(home.html , r ,encoding=utf8 )作为f:
s=f.read()
返回字节(s,编码=utf8 )
#定义url和要执行的实际功能之间的对应关系
list1=[
(/index/,index),
(/home/,home),
]
而1:
#等待连接
conn,add=sk.accept()
Data=conn.recv(8096) #接收来自客户端的消息
#从数据中获取路径
Data=str (data,encoding= UTF8) #将接收到的字节类型数据转换为字符串。
#拆分者\r\n
data1=data.split(\r\n)[0]
Url=data1.split()[1] # url是我们从浏览器发送的消息中分离出来的访问路径。
conn . send(b HTTP/1.1 200 ok \ r \ n \ r \ n )#因为应该遵循HTTP协议,所以回复消息也应该有一个状态行。
#根据不同的路径返回不同的内容
Func=None #定义一个保存要执行的函数名称的变量。
对于列表1中的I:
if i[0]==url:
func=i[1]
破裂
if func:
response=func(url)
否则:
response=b 找不到404!
#返回特定的响应消息
conn.send(响应)
conn.close()
好了,停在这里。
python web程序的程序和应用程序在现实开发中,一般分为两部分:服务器程序和应用程序。
服务器程序负责封装socket服务器,在请求到来的时候整理出各种被请求的数据。
应用程序负责具体的逻辑处理。为了方便应用的开发,出现了很多Web框架,如Django、Flask、web.py等。不同的框架有不同的开发方法,但无论如何,开发的应用程序必须与服务器程序配合,为用户提供服务。
这样,服务器程序需要为不同的框架提供不同的支持。这种混乱的情况对服务器和框架都是不利的。对于服务器来说,需要支持各种框架。对于框架,只有支持它的服务器才能被开发的应用程序使用。
这个时候,标准化就变得尤为重要。我们可以设定一个标准,只要服务器程序支持这个标准,框架支持这个标准,那么它们就可以一起使用。标准一旦确定,双方就各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。
WSGI(web服务器网关接口)是一个规范,它定义了用Python编写的web应用程序与web服务器程序之间的接口格式,实现了Web应用程序与Web服务器程序的解耦。
常用的WSGI服务器有uwsgi和Gunicorn。Python标准库提供的独立WSGI服务器称为wsgiref,Django开发环境使用该模块作为服务器。
从这里继续。
Wsgiref我们用wsgiref模块来代替我们自己的web框架的socket服务器部分:
在URL-function高级版中根据不同的路径返回不同的内容
返回HTML页面
使网页动态化。
Wsgiref模块版本
导入时间
从wsgiref.simple_server导入make_server
#将返回的不同内容部分封装到函数中
定义索引(url):
用open(index.html , r ,encoding=utf8 )作为f:
s=f.read()
now=str(time.time())
s=s.replace(@@oo@@ ,现在)
返回字节(s,编码=utf8 )
定义主页(url):
用open(home.html , r ,encoding=utf8 )作为f:
s=f.read()
返回字节(s,编码=utf8 )
#定义url和要执行的实际功能之间的对应关系
list1=[
(/index/,index),
(/home/,home),
]
def运行服务器(环境,启动响应):
start_response(200 OK ,[(Content-Type , text/html;Charset=utf8 ),]) #设置HTTP响应的状态码和头信息
Url=environ[PATH_INFO] #获取用户输入的Url。
func=无
对于列表1中的I:
if i[0]==url:
func=i[1]
破裂
if func:
response=func(url)
否则:
response=b 找不到404!
返回[响应,]
if __name__==__main__ :
httpd=make_server(127.0.0.1 ,8090,run_server)
打印(我在8090等你.)
httpd.serve_forever()
上面的代码jinja2实现了一个简单的动态,我可以从数据库中查询数据,然后在我的html中替换相应的内容,然后发送给浏览器完成渲染。这个过程相当于HTML模板渲染数据。本质上,HTML内容使用一些特殊的符号来替换要显示的数据。我在这里使用的特殊符号是我自己定义的。其实模板渲染有一个现成的工具:jinja2。
下载jinja2:
pip安装jinja2
!声明文档类型
html lang=zh-CN
头
meta charset=UTF-8
meta http-equiv= x-ua-compatible content= IE=edge
meta name= viewport content= width=device-width,initial-scale=1
标题标题/标题
/头
身体
H1姓名:{ {姓名}} /h1
H1爱好:/h1
保险商实验所
{%用于hobby_list %}中的爱好
李{ {爱好} }/李
{% endfor %}
/ul
/body
/html index2.html文件
用jinja2渲染index2.html文件:
从wsgiref.simple_server导入make_server
从jinja2导入模板
定义索引():
用open(index2.html , r )作为f:
data=f.read()
Template=Template(data) #生成模板文件
ret=template . render({ name : Alex , hobby _ list: [perm , bubble bar]}) #将数据填入模板。
return [bytes(ret,encoding=utf8 ),]
def home():
用open(home.html , rb )作为f:
data=f.read()
返回[数据,]
#定义url和函数之间的对应关系
URL_LIST=[
(/index/,index),
(/home/,home),
]
def运行服务器(环境,启动响应):
start_response(200 OK ,[(Content-Type , text/html;Charset=utf8 ),]) #设置HTTP响应的状态码和头信息
Url=environ[PATH_INFO] #获取用户输入的Url。
Func=None #要执行的函数
对于URL_LIST中的I:
if i[0]==url:
Func=i[1] #转到前面定义的url列表,查找url应该执行的功能。
破裂
If func: #如果你能找到要执行的函数
Return func() #返回函数的执行结果
否则:
Return [bytes(404没有这个页面,encoding=utf8 ),]
if __name__==__main__ :
httpd=make_server(,8000,run_server)
打印(在端口8000上提供HTTP服务.)
httpd.serve_forever()
现在的数据是我们自己手写的,那可不可以从数据库中查询数据,来填充页面呢?
使用已安装连接数据库:
conn=pymysql。连接(host= 127。0 .0 .1 ,端口=3306,用户=root ,密码=xxx ,数据库=xxx ,字符集=utf8 )
cursor=conn . cursor(cursor=pymysql。光标。字典光标)
cursor.execute(从用户信息中选择姓名,年龄,部门标识)
user_list=cursor.fetchall()
cursor.close()
conn.close()
创建一个测试的用户表:
创建表用户(
id int自动递增主键
名称字符(10)不为空,
爱好字符(20)不为空
)engine=innodb DEFAULT charset=UTF8;模板的原理就是字符串替换,我们只要在超文本标记语言页面中遵循jinja2的语法规则写上,其内部就会按照指定的语法进行相应的替换,从而达到动态的返回内容。
姜戈姜戈官网下载页面
安装(安装最新逻辑理论专家系统版):pip3 install django==1.11.9创建一个框架项目:下面的命令创建了一个名为"我的网站"的姜戈项目:
姜戈-管理开始项目我的网站目录介绍:
我的网站/
manage.py #管理文件
我的网站#项目目录
__init__ .巴拉圭
设置。py #配置
网址。py #路由-网址和函数的对应关系
wsgi.py # runserver命令就使用wsgiref模块做简单的网络服务器
运行姜戈项目:python管理。py runserver 127。0 .0 .1:8000模板文件配置:
模板=[
{
后端姜戈。模板。后端。姜戈。django模板,
DIRS: [os.path.join(BASE_DIR, template)],# template文件夹位置
APP_DIRS :对,
选项:{
上下文处理者:[
姜戈。模板。上下文处理器。调试,
姜戈。模板。上下文处理器。请求,
姜戈。贡献。auth。上下文处理器。授权,
姜戈。贡献。消息。上下文处理器。消息,
],
},
},
]
静态文件配置:STATIC_URL=/static/ # HTML中使用的静态文件夹前缀
STATICFILES_DIRS=[
os.path.join(BASE_DIR, static ),#静态文件存放位置
]看不明白?有图有真相:
刚开始学习时可在配置文件中暂时禁用跨站点请求伪造中间件,方便表单提交测试。
中间件=[
姜戈。中间件。安全。安全中间件,
姜戈。贡献。会话。中间件。会话中间件,
姜戈。中间件。常见。通用中间件,
# 姜戈。中间件。csrf。 csrfviewmiddleware ,
姜戈。贡献。auth。中间件。认证中间件,
姜戈。贡献。消息。中间件。消息中间件,
姜戈。中间件。点击顶举。xframeoptions中间件,
]
姜戈基础必备三件套:从django .捷径导入HttpResponse,render,redirectHttpResponse内部传入一个字符串参数,返回给浏览器。
例如:
定义索引(请求):
# 业务逻辑代码
返回HttpResponse(确定)呈现除请求参数外还接受一个待渲染的模板文件和一个保存具体数据的字典参数。
将数据填充进模板文件,最后把结果返回给浏览器。(类似于我们上面用到的jinja2)
例如:
定义索引(请求):
# 业务逻辑代码
return render(请求, index.html ,{ 姓名:亚历克斯,爱好:[烫头, 泡吧]})重定向接受一个统一资源定位器参数,表示跳转到指定的网址。
例如:
定义索引(请求):
# 业务逻辑代码
返回重定向(/home/)重定向是怎么回事?
练习:Django版登录
启动姜戈报错:Django启动时报错unicode编码错误.
报这个错误通常是因为计算机名为中文,改成英文的计算机名重启下电脑就可以了。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。