Web 服务器
每个页面都以 HTML 的形式传送到你的浏览器中,HTML 是一种浏览器用来描述页面内容和结构的语言。那些负责发送 HTML 到浏览器的应用称之为“Web 服务器”,会让你迷惑的是,这些应用运行的机器通常也叫做 web 服务器。
然而,最重要的是要理解,到最后所有的 web 应用要做的事情就是发送 HTML 到浏览器。不管应用的逻辑多么复杂,最终的结果总是将 HTML 发送到浏览器(我故意将应用可以响应像 JSON
或者 CSS
等不同类型的数据忽略掉,因为在概念上是相同的)。
HTTP GET
web 应用在 GET 请求的结果中,不应该改变应用的状态(比如,不能基于 GET 请求创建一个新帐号)。正是因为这个原因,GET 请求通常认为是“安全”的,因为他们不会导致应用的改变。
HTTP POST
POST 请求通常携带由用户输入的数据,web 应用收到之后会产生一些行为。通过在表单里输入你的信息登录一个网站,就是 POST 表单的数据给 web 应用的。
框架的概念:
特指为解决一个开放性问题而设计的具有一定约束性的支撑结构。在此结构上可以根据具体问题扩展、安插更多的组成部分,从而更迅速和方便地构建完整的解决问题的方案
python中web框架按是否包含socket分为俩类:
1、tornado--------socket + 业务逻辑处理
2、Django,bottle,flack-----业务逻辑处理 (本身包含) + 第三方模块(wsgiref)(其中包含socket)
一、初识tornado
tornado web server 是使用python编写出来的一个轻量级、高可伸缩性和非阻塞IO的Web服务器软件,其特点是采用epoll非阻塞IO,相应快速,可处理数千并发连接,特别适用于实时的Web服务。
MVC和MTV框架------(其实就是文件夹的分类)
MVC:Models 数据相关操作(数据库) Views 模板HTML文件 Controllers 业务逻辑(url)
MTV:Models 数据相关操作(数据库) Templates 模板HTML文件 Views 业务逻辑(url)
web框架的本质
经典的hello world 案例:
import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") application = tornado.web.Application([ (r"/index", MainHandler), #路由映射(路由系统) ]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
第一步:执行脚本,监听 8888 端口
第二步:浏览器客户端访问 /index --> http://127.0.0.1:8888/index
第三步:服务器接受请求,并交由对应的类处理该请求
第四步:类接受到请求之后,根据请求方式(post / get / delete ...)的不同调用并执行相应的方法
第五步:方法返回值的字符串内容发送浏览器
具体分析后
import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): # self.render("s1.html") #render方法,表示会自动找到文件并打开,返回给你 #render找的时候默认从当前的目录下面去找,如果想让其从别的地方找,我们就可以 #为其做一个settings配置(也可以把绝对路径写上去), self.write("Hello, world") settings={ #如果想让配置文件生效,需要在下面application后面加一个**settings "tempalte_path":"xxx", #模板路径的匹配,其中xxx为放HTML的文件夹 "static_path":"xxx" #静态文件的配置(静态文件就是css和JavaScript),其中xxx为存放静态文件的文件夹 } #路由映射(路由系统) application = tornado.web.Application([ (r"/index", MainHandler), #检测用户的url是否匹配,如果匹配则,执行其后面类中的莫一种方法 #同一个url以不同的方式访问,执行不同的方法 ],**settings) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
前端与后台互动实例
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.ioloop import tornado.web list = [] class MainHandler(tornado.web.RequestHandler): def get(self): #1、打开s.html,读取内容(含有特殊语法-----模板语言) #2、xxx = list和特殊的语法进行结合, #3、得到一个新的经过渲染后的字符串返回给用户 self.render('s.html' ,xxx = list) def post(self, *args, **kwargs): data = self.get_argument("xxx") #用于通过键值获取后台以键值对提交的数据 print(data) list.append(data) self.render("s.html",xxx = list) #xxx = list 表示用于渲染时的值 settings={ "template_path":"ttt", "static_path":"static" } application = tornado.web.Application([ (r"/index", MainHandler), ],**settings) if __name__ == "__main__": application.listen(8080) tornado.ioloop.IOLoop.instance().start()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="../static/commons.css"> </head> <body> <h1>提交内容</h1> <form action="/index" method="post"> <!--以post方式提交会执行post方法-,/index 表示提交的url地址--> <input type="text" name="xxx"> <input type="submit"> </form> <h1>显示内容</h1> <ul> {% for item in xxx %} <li>{{item}}</li> {% end %} </ul> </body> </html>
总结点:
self.get_argument("xxx",None)----------------用于获取后台提交的数据,其中None为默认值
提交方式:get 和 post提交方式的不同点 ---------get可以通过url方式提交
模板语言里通过for循环展示数据:
{% for item in xxx %} -------必须是{% %}的格式
<li>{{item}}</li> --------item必须{{}}包裹起来
{% end %} --------结束必须有{% end %}
模板语言(3种):
1、{{xxx}}-------------self.render("s.html",xxx = "yyy")
2、代码块的方式
{% for item in xxx %}-------------- self.render("s.html",xxx = yyy) {% if item == "alex"%} .....................
<li>{{item}}</li> {% else %}
{% end %} {% end %}
3、自定义
1>uimethods
---------------->在HTML中<span>{{fun(arg)}}</span>
---------------->新建一个uimethods文件,并在其中定义方法 def fun(self,arg): return xxx
---------------->主程序中需要导入 import uimethods as mt 并配置文件 'ui_methods': mt, 在render中传参 self.render("s.html",xxx = yyy,arg = "aaaa")
settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'ui_methods': mt,
'ui_modules': md,
}
# uimethods.py
def tab(self):
return 'UIMethod'
2>uimodules
---------------->在HTML中<span>{% module 类名()%}</span>
---------------->新建一个uimodules文件,并在其中类等的一些东西
---------------->主程序中需要导入 import uimodules as md 并配置文件 'ui_modules: md,
#!/usr/bin/env python # -*- coding:utf-8 -*- from tornado.web import UIModule from tornado import escape class custom(UIModule): def render(self, *args, **kwargs): return escape.xhtml_escape('<h1>wupeiqi</h1>') #return escape.xhtml_escape('<h1>wupeiqi</h1>')
注册和使用
#!/usr/bin/env python # -*- coding:utf-8 -*- #!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.ioloop import tornado.web from tornado.escape import linkify import uimodules as md import uimethods as mt class MainHandler(tornado.web.RequestHandler): def get(self): self.render('index.html') settings = { 'template_path': 'template', 'static_path': 'static', 'static_url_prefix': '/static/', 'ui_methods': mt, 'ui_modules': md, } application = tornado.web.Application([ (r"/index", MainHandler), ], **settings) if __name__ == "__main__": application.listen(8009) tornado.ioloop.IOLoop.instance().start()
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <link href="{{static_url("commons.css")}}" rel="stylesheet" /> </head> <body> <h1>hello</h1> {% module custom(123) %} {{ tab() }} </body>
在模板中默认提供了一些函数、字段、类以供模板使用:
escape
: tornado.escape.xhtml_escape
的別名----------------------------------------------用来做转译的
xhtml_escape
:tornado.escape.xhtml_escape
的別名------------------------------------用来做转译的url_escape
:tornado.escape.url_escape
的別名------------------------------------------用来做转译的json_encode
:tornado.escape.json_encode
的別名---------------------------------------用来做json处理的squeeze
:tornado.escape.squeeze
的別名linkify
:tornado.escape.linkify
的別名--------------------------------------------------用来生成a标签的datetime
: Python 的datetime
模组handler
: 当前的RequestHandler
对象request
:handler.request
的別名current_user
:handler.current_user
的別名locale
:handler.locale
的別名_
:handler.locale.translate
的別名static_url
: forhandler.static_url
的別名--------------------用于css文件或js的缓存作用(v=675645434545,这是文件的md5值)xsrf_form_html
:handler.xsrf_form_html
的別名
cookie
Cookie是当你浏览某网站时,网站存储在你机器上的一个小文本文件,它记录了你的用户ID,密码、浏览过的网页、停留的时间等信息,当你再次来到该网站时,网站通过读取Cookie,得知你的相关信息,就可以做出相应的动作,如在页面显示欢迎你的标语,或者让你不用输入ID、密码就直接登录等。
登录设置cookie实例:
import tornado.ioloop import tornado.web from controller import index from controller import login settings={ "template_path":"views", "static_path":"statics", 'cookie_secret':"wdfsdfsfsd" } application = tornado.web.Application([ (r"/index", index.IndexHandler), (r"/login", login.LoginHandler), ],**settings) if __name__ == "__main__": application.listen(8080) tornado.ioloop.IOLoop.instance().start()
import tornado.web class IndexHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): cook = self.get_secure_cookie("auto") #获取cookie if cook: #如果以前登录成功过,会获得cookie,未登录成功直接访问,默认为None self.render("index.html") #如果有cookie,则返回需要页 else: self.write("访问失败") def post(self, *args, **kwargs): user = self.get_argument("username") #获取登录页输入的用户名 pwd = self.get_argument("pwd") #获取登录页的密码 if user == "alex" and pwd =="123": self.set_secure_cookie("auto","666") #如果登录成功,则设置cookie self.render("index.html") #登录成功返回需要访问页码 else: self.redirect("/login") #登录不正确,跳转登录页
import tornado import tornado.web class LoginHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): self.render("login.html") def post(self, *args, **kwargs): pass
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>活跃288天,已升级</h1> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/index" method="post"> <input type="text" name="username"> <input type="password" name="pwd"> <input type="submit" value="提交"> </form> </body> </html>