pythonweb模板
⑴ 纯 python 写一个 Web 框架,就是这么简单
造轮子是最好的一种学习方式,本文尝试从0开始造个Python Web框架的轮子,我称它为 ToyWebF 。
本文操作环境为:MacOS,文中涉及的命令,请根据自己的系统进行替换。
ToyWebF的简单特性:
下面我们来实现这些特性。
首先,我们需要安装gunicorn,回忆一下Flask框架,该框架有内置的Web服务器,但不稳定,所以上线时通常会替换成uWSGI或gunicorn,这里不搞这个内置Web服务,直接使用gunicorn。
我们创建新的目录与Python虚拟环境,在该虚拟环境中安装gunicorn
在啥都没有的情况下,构建最简单的Web服务,在ToyWebF目录下,创建app.py与api.py文件,写入下面代码。
运行 gunicorn app:app 访问 http://127.0.0.1:8000 ,可以看见 Hello, World! ,但现在请求体中的参数在environ变量中,难以解析,我们返回的response也是bytes形式。
我们可以使用webob库,将environ中的数据转为Request对象,将需要返回的数据转为Response对象,处理起来更加直观方便,直接通过pip安装一下。
然后修改一下API类的 __call__方法 ,代码如下。
上述代码中,通过webob库的Request类将environ对象(请求的环境信息)转为容易处理的request,随后调用handle_request方法对request进行处理,处理的结果,通过response对象返回。
handle_request方法在ToyWebF中非常重要,它会匹配出某个路由对应的处理方法,然后调用该方法处理请求并将处理的结果返回,在解析handle_request前,需要先讨论路由注册实现,代码如下。
其实就是将路由和方法存到self.routes字典中,可以通过route装饰器的形式将路由和方法关联,也可以通过add_route方法关联,在app.py中使用一下。
因为url中可以存在变量,如 @app.route("/hello/{name}") ,所以在匹配时,需要进行解析,可以使用正则匹配的方式进行匹配,parse这个第三方库已经帮我们实现了相应的正则匹配逻辑,pip安装使用一下则可。
这里定义find_handler方法来实现对self.routes的遍历。
了解了路由与方法关联的原理后,就可以实现handle_request方法,该方法主要的路径就是根据路由调度对应的方法,代码如下。
在该方法中,首先实例化webob库的Response对象,然后通过self.find_handler方法获取此次请求路由对应的方法和对应的参数,比如。
它将返回hello方法对象和name参数,如果是 /hello/二两 ,那么name就是二两。
因为route装饰器可能装饰器的类对象,比如。
此时self.find_handler方法返回的hanler就是个类,但我们希望调用的是类中的get、post、delete等方法,所以需要一个简单的判断逻辑,通过inspect.isclass方法判断handler如果是类对象,那么就通过getattr方法获取类对象实例的中对应的请求方法。
如果类对象中没有该方法属性,则抛出该请求类型不被允许的错误,如果不是类对象或类对象中存在该方法属性,则直接调用则可。
此外,如果方法的路由并没有注册到self.routes中,即404的情况,定义了defalut_response方法返回其中内容,代码如下。
如果handle_request方法中调度的过程出现问题,则直接raise将错误抛出。
至此,一个最简单的web服务就编写完成了。
回顾Flask,Flask可以支持HTML、CSS、javaScript等静态文件,利用模板语言,可以构建出简单但美观的Web应用,我们让TopWebF也支持这一功能,最终实现图中的网站,完美兼容静态文件。
Flask使用了jinja2作为其html模板引擎,ToyWebF同样使用jinja2,jinja2其实实现一种简单的DSL(领域内语言),让我们可以在HTML中通过特殊的语法改变HTML的结构,该项目非常值得研究学习。
首先 pip install jinja2 ,然后就可以使用它了,在ToyWebF项目目录中创建templates目录,以该目录作为默认的HTML文件根目录,代码如下。
首先利用jinja2的FileSystemLoader类将file system中的某个文件夹作为loader,然后初始化Environment。
在使用的过程中(即调用template方法),通过get_template方法获得具体的某个模板并通过render方法将对应的内容传递给模板中的变量。
这里我们不写前端代码,直接去互联网中下载模板,这里下载了Bootstrap提供的免费模板,可以自行去 https://startbootstrap.com/themes/freelancer/ 下载,下载完后,你会获得index.html以及对应的css、jss、img等文件,将index.html移动到ToyWebF/templates中并简单修改了一下,添加一些变量。
然后在app.py文件中为index.html定义路由以及需要的参数。
至此html文件的支持就完成了,但此时的html无法正常载入css和js,导致页面布局非常丑陋且交互无法使用。
接着就让ToyWebF支持css、js,首先在ToyWebF目录下创建static文件夹用于存放css、js或img等静态文件,随后直接将前面下载的模板,其中的静态文件复制到static中则可。
通过whitenoise第三方库,可以通过简单的几行代码让web框架支持css和js,不需要依赖nginx等服务,首先 pip install whitenoise ,随后修改API类的 __init__ 方法,代码如下。
其实就是通过WhiteNoise将self.wsgi_app方法包裹起来,在调用API的 __call__ 方法时,直接调用self.whitenoise。
此时,如果请求web服务获取css、js等静态资源,WhiteNoise会获取其内容并返回给client,它在背后会匹配静态资源在系统中对应的文件并将其读取返回。
至此,一开始的网页效果就实现好了。
web服务如果出现500时,默认会返回 internal server error ,这显得比较丑,为了让框架使用者可以自定义500时返回的错误,需要添加一些代码。
首先API初始化时,初始self.exception_handler对象并定义对应的方法添加自定义的错误
在handler_request方法进行请求调度时,调度的方法执行逻辑时报500,此时不再默认将错误抛出,而是先判断是否有自定义错误处理。
在app.py中,自定义错误返回方法,如下。
custom_exception_handler方法只返回自定义的一段话,你完全可以替换成美观的template。
我们可以实验性定义一个路由来看效果。
Web服务的中间件也可以理解成钩子,即在请求前可以对请求做一些处理或者返回Response前对Response做一下处理。
为了支持中间件,在TopWebF目录下创建middleware.py文件,在编写代码前,思考一下如何实现?
回顾一下现在请求的调度逻辑。
1.通过routes装饰器关联路由和方法 2.通过API.whitenoise处理 3.如果是请求API接口,那么会将参数传递给API.wsgi_app 4.API.wsgi_app最终会调用API.handle_request方法获取路由对应的方法并调用该方法执行相应的逻辑
如果希望在request前以及response后做相应的操作,那么其实就需要让逻辑在API.handle_request前后执行,看一下代码。
其中add方法会实例化Middleware对象,该对象会将当前的API类实例包裹起来。
Middleware.handle_request方法其实就是在self.app.handle_request前调用self.process_request方法处理request前的数据以及调用self.process_response处理response后的数据,而核心的调度逻辑,依旧交由API.handle_request方法进行处理。
这里的代码可能会让人感到疑惑, __call__ 方法和handle_request方法中都有self.app.handle_request(request),但其调用对象似乎不同?这个问题暂时放一下,先继续完善代码,然后再回来解释。
接着在api.py中为API创建middleware属性以及添加新中间件的方法。
随后,在app.py中,自定义一个简单的中间件,然后调用add_middleware方法将其添加。
定义好中间件后,在请求调度时,就需要使用中间件,为了兼容静态文件的情况,需要对css、js、ing文件的请求路径做一下兼容,在其路径中加上/static前缀
紧接着,修改API的 __call__ ,兼容中间件和静态文件,代码如下。
至此,中间件的逻辑就完成了。
但代码中依旧有疑惑,Middleware类中的 __call__ 方法和handle_request方法其调用的self.app到底是谁?
为了方便理解,这里一步步拆解。
如果没有添加新的中间件,那么请求的调度逻辑如下。
在没有添加中间件的情况下,self.app其实就是API本身,所以 middleware.__call__ 中的self.app.handle_request就是调用API.handle_request。
如果添加了新的中间件,如上述代码中添加了名为SimpleCustomMiddleware的中间件,此时的请求调度逻辑如下。
因为注册中间件时,Middleware.add方法替换了原始Middleware实例中的app对象,将其替换成了SimpleCustomMiddleware,而SimpleCustomMiddleware也有app对象,SimpleCustomMiddleware中的app对象,才是API类实例。
在请求调度的过程中,就会触发Middleware类的handle_request方法,该方法就会执行中间件相应的逻辑去处理request和response中的数据。
当然,你可以通过Middleware.add方法添加多个中间件,这就会构成栈式调用的效果,代码如下。
启动web服务后,其执行效果如下。
⑵ Python的Flask框架中web表单
下面为你介绍了Python的Flask框架中判游web表单的教程,表单是学习各个web框架中的基础知识,需要的朋友可以参考下
概要
在前面章节我们为主页定义了一个简单的模板,部分尚未实现的模块如用户或帖子等使用模拟的对象作为临时占位。
本章我们将看到如何利用web表单填补这些空白。
web表单是web应用中最基本的构建要素,我们将通过表单来实现用户发帖和应用登录功能。
完成本章内容你需要基于前面章节完成的微博应用代码,请确认这些代码已安装并能正常运行。
配置
Flask-WTF是WTForms项目的Flask框架扩展,我们将用他来帮助我们处理web表单。
大部分Flask扩展都需要定义相关配置项,所以我们先来在应用根目录下创建一个配置文件以备使用。我们先这样创建 (fileconfig.py):
SRF_ENABLED = True
SECRET_KEY = you-will-never-guess
很简单吧,这是Flask-WTF需要用到的2个配置项。CSRF_ENABLED配置启用了跨站请求攻击保护,大部分情况下你都需要开启此功能,这能使你的应用更安全。
SECRET_KEY设置当CSRF启用时有效,这将生成一个加密的token供表单验证使用,你要确保这个KEY足够复杂不会被简单推测。
现在这个配置文件已经基本可用了。项目创建完成我们可以创建如下文件并编辑(fileapp/__init__.py):
?
from flask import Flask
app = Flask(__name__)
app.config.from_object(config)
from app import views
用户登录表单
使用Flask-WTF创建的表单就像一个对象,需要从Form类继承子类。然后在这个子类中定义一些类的属性变量作为表单字段就可以了。
我们要创建一个登录表单,用来进行用户身份识别。但跟平常需要验证用户名和密码的登录方式不同,我们将使用 OpenId 来处理登录过程。使用OpenId的好处就是我们不用管那些用户名和密码的认证过程,交给 OpenId 去搞定,它会返回给我们用户验证后的数据。这样对于使用我们网站的用户而言也更安全。
使用 OpenId 登录只需要一个字符串,然后发送给 OpenId 服务器就行了。另外我们还需要在表单中加一个“记住我” 的选项框,这个是送给那些不想每次来我们网站都要进行身份认证的人。选择这个选项后,首次登录时会用cookie在他们的浏览器上记住他们的登录信息,下次再进入网站时就不需要进行登录操作。
开始我们的第一个表单吧 (fileapp/forms.py):
?
from flask.ext.wtf import Form, TextField, BooleanField
from flask.ext.wtf import Required
class LoginForm(Form):
openid = TextField(openid, validators = [Required()])
remember_me = BooleanField(remember_me, default = False)
欣赏一下这个类,多么的简洁,多么的一目了然。如此简单,但又十分的富有内涵。我们引入了一个 Form 类,然后继承这个类,按需求还添加了 TextField 和 BooleanField 这两个字段。
另外还引入了一个表单验证函数 Required,这种验证函数可以附加在字段里面,在用户提交表单时它们会用来检查用户填写的数据。这个 Required 函数是用来防止用户提交空数据。Flask-WTF 中还有掘冲碧很多不同作用的表单验证函数,我们将会在后面使用到它们。
表单模板
现在我们的问题就是需要一个显示这个登录表单的模板。好消息是我们刚刚创建的登录表单类知道如何把字段转换成HTML,所以我们只需要把注意力集判举中到页面布局上。下面就是我们的登录表单的模板 (fileapp/templates/login.html):
-- extend from base layout --
{% extends base.html %}
{% block content %}
h1Sign In/h1
form action= method=post name=login
{{form.hidden_tag()}}
p
Please enter your OpenID:br
{{form.openid(size=80)}}br
/p
p{{form.remember_me}} Remember Me/p
pinput type=submit value=Sign In/p
/form
{% endblock %}
容我_嗦一下,在这个模板中,我们又一次使用了模板继承的方式。使用 extends 语句从 base.html 继承模板内容。我们会在后面创建的模板中继续使用这种方式,这样可以使我们所有的页面布局保持一致。
这个登录模板跟普通的HTML表单有些明显的区别,它使用模板参数 {{ ... }} 来实例化表单字段,而表单字段又来源于我们刚刚定义的表单类,模板参数中使用了 form 这个名称。当我们使用视图函数引用表单类并渲染到模板时,我们要特别注意这个把表单类传递到模板的变量名。
我们在配置中开启了CSRF(跨站伪造请求)功能,模板参数 {{ form.hidden_tag() }} 会被替换成一个具有防止CSRF功能的隐藏表单字段。在开启了CSRF功能后,所有模板的表单中都需要添加这个模板参数。
我们定义的表单对象中的字段同样也能被模板渲染,只需要在模板合适的位置添加类似于 {{ form.field_name }} 这样的模板参数,相关字段就会在被定义的位置出现。另外还有一些字段是可以传参数,比如这个 openid 字段,我们就添加了一个参数让它显示的宽度增加到80个字符。
由于我们没有在表单中定义一个提交功能的按钮,所以在这里只能以普通表单字段的方式来做了。不过说起来区区一个按钮,在表单中跟任何数据都没有关系,的确也没有在表单类中定义的必要。
表单视图
见证奇迹的时刻最后一步,我们马上要来写一个渲染登录表单对象到模板的视图函数。
这个函数相当的简单无趣,因为我们只需要把表单对象传递给模板就行了。下面就是我们这个视图函数的全部内容 (fileapp/views.py):
11
12
from flask import render_template, flash, redirect
from app import app
from forms import LoginForm
# index view function suppressed for brevity
@app.route(/login, methods = [GET, POST])
def login():
form = LoginForm()
return render_template(login.html,
title = Sign In,
form = form)
我们引入登录表单类,然后把它实例化到一个变量,最后再把这个变量传给模板。要渲染表单字段必须的事情也就这些。
上面的代码中还引入了两个新对象: falsh 和 redirect, 这个先甭理它们,稍后才用得上。
另外还做了一件事就是在路由装饰器中添加一个新方法。让 Flask 明白我们这个视图函数支持 GET 和 POST 请求。否则这个视图函数只会响应 GET 请求。我们需要得到用户填写表单后提交的数据,这些数据是从 POST 请求中传递过来的。
你可以通过在浏览器中测试这个程序来了解上面所说的。 按照视图函数关联的路由,你应该在浏览器中输入
由于我们还没有写任何接收数据的代码,所以现在你在页面中点提交按钮还没有任何效果。
从表单中接收数据
另外值得一提的是, Flask-WTF 对表单提交数据的处理使我们的接下来要做的事情变得简单了。下面就是我们这个登录视图函数的新版本, 加入了表单数据验证和处理 (fileapp/views.py):
?
7
8
9
@app.route(/login, methods = [GET, POST])
def login():
form = LoginForm()
if form.validate_on_submit():
flash(Login requested for OpenID= + form.openid.data + , remember_me= + str(form.remember_me.data))
return redirect(/index)
return render_template(login.html,
title = Sign In,
form = form)
validate_on_submit() 这个方法做了表单处理的所有工作。如果你在表单向用户提供数据时(举个栗子:用户在它之前修改了一下提交的数据) 时调用此方法,它会返回 False。发生这样的情况时,你懂的。不懂?就是提交的数据验证不通过,你要继续渲染模板。
在提交请求时调用了表单的 validate_on_submit() 方法后,它会从请求中获取所有提交的数据,然后使用表单字段中绑定的验证函数进行数据验证。在所有的数据都验证通过时会返回 True. 这就意味着你可以放心的使用这些表单数据了。
只要有一个字段验证不通过,它都会返回 False. 这时就需要我们返回数据给用户,让他们来纠正一下错误数据。接下来我们将会看到在数据验证失败时,如何把错误消息显示给用户。
当 validate_on_submit() 方法返回 True 的时候,我们的视图函数又会调用两个新的函数。它们都是从Flask 中引入的,flash 函数用来在下一个打开的页面中显示定义的消息。我们现在用它用来做调试。因为我们现在还没有做用户登录模块, 所以只需要把用户提交上来的数据显示一下就行了。flash 函数非常有用,比如为用户的一些操作提供消息反馈。
flash 函数提供的消息不会自动出现在我们的网站页面中,所以我们需要做点事情让它在页面中显示出来。为了让我们所有页面都能有这项激动人心的功能,所以就把它添加到基础模板中吧, 下面是更新后的基础模板 (fileapp/templates/base.html):
html
head
{% if title %}
title{{title}} - microblog/title
{% else %}
titlemicroblog/title
{% endif %}
/head
body
divMicroblog: a href=/indexHome/a/div
hr
{% with messages = get_flashed_messages() %}
{% if messages %}
ul
{% for message in messages %}
li{{ message }} /li
{% endfor %}
/ul
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
/body
/html
模板中显示 flash 消息的功能希望你能明白。
在视图函数中我们使用的另一个新函数就是 redirect. 这个函数会通知用户的浏览器跳转到指定的地址。在我们的视图函数中,我们使用它跳转到了首页。注意跳转结束后页面上还会显示 flash 函数传递的消息哦。
激动人心的时刻到了,运行我们的程序吧,看看表单是如何工作的吧。不要填写表单中的 openid 字段,看看 Required 这个验证函数是如何发挥威力,把一切发起空数据的请求阻止在千里之外。
改善一下字段验证
我们程序目前状况不错,提交不合要求的数据会被阻止,还会返回表单让用户修改,基本满足我们要求。
但似乎还少点什么。如果我们在用户提交数据失败后给用户点提示,让他们知道什么原因引起的,岂不妙哉!太幸运了,用 Flask-WTF 可以轻松解决这个问题。
当表单字段验证失败时, Flask-WTF 会添加一个错误消息到表单对象。这些消息在模板中也是可以使用的,所以我们只需要在模板中添加一点点东西就OK了。
这个就是我们添加了验证消息的登录模板 (fileapp/templates/login.html):
16
17
18
!-- extend base layout --
{% extends base.html %}
{% block content %}
h1Sign In/h1
form action= method=post name=login
{{form.hidden_tag()}}
p
Please enter your OpenID:br
{{form.openid(size=80)}}br
{% for error in form.errors.openid %}
span style=color: red;[{{error}}]/span
{% endfor %}br
/p
p{{form.remember_me}} Remember Me/p
pinput type=submit value=Sign In/p
/form
{% endblock %}
我们仅在 openid 字段的右边添加了一个循环语句,它会把openid字段验证失败的消息都显示出来。不论你的表单有多少字段,所有表单字段验证失败的错误消息都可以用 form.errors.字段名 这种方式来使用。这个表单中我们的是 form.errors.openid。为了让错误消息引起用户的注意,我们还给消息添加了显示红色的 css 样式。
处理 OpenID 登录
现实生活中,我们发现有很多人都不知道他们拥有一些公共账号。一部分大牌的网站或服务商都会为他们的会员提供公共账号的认证。举个栗子,如果你有一个 google 账号,其实你就有了一个公共账号,类似的还有 Yahoo, AOL, Flickr 等。
为了方便我们的用户能简单的使用他们的公共账号,我们将把这些公共账号的链接添加到一个列表,这样用户就不用自手工输入了。
我们要把一些提供给用户的公共账号服务商定义到一个列表里面,这个列表就放到配置文件中吧 (fileconfig.py):
?
7
8
9
CSRF_ENABLED = True
SECRET_KEY = you-will-never-guess
OPENID_PROVIDERS = [
{ name: Google, url:
{ name: Yahoo, url:
{ name: AOL, url:
{ name: Flickr, url:
{ name: MyOpenID, url:
}]
接下来就是要在我们的登录视图函数中使用这个列表了:
@app.route(/login, methods = [GET, POST])
def login():
form = LoginForm()
if form.validate_on_submit():
flash(Login requested for OpenID= + form.openid.data + , remember_me= + str(form.remember_me.data))
return redirect(/index)
return render_template(login.html,
title = Sign In,
form = form,
providers = app.config[OPENID_PROVIDERS])
我们从 app.config 中引入了公共账号服务商的配置列表,然后把它作为一个参数通过 render_template 函数引入到模板。
接下来要做的我想你也猜得到,我们需要在登录模板中把这些服务商链接显示出来。
24
25
26
27
28
29
30
31
32
33
34
!-- extend base layout --
{% extends base.html %}
{% block content %}
script type=text/javascript
function set_openid(openid, pr)
{
u = openid.search(username)
if (u != -1) {
// openid requires username
user = prompt(Enter your
+ pr +
username:)
openid = openid.substr(0, u) + user
}
form = document.forms[login];
form.elements[openid].value = openid
}
/script
h1Sign In/h1
form action= method=post name=login
{{form.hidden_tag()}}
p
Please enter your OpenID, or select one of the providers below:br
{{form.openid(size=80)}}
{% for error in form.errors.openid %}
span style=color: red;[{{error}}]/span
{% endfor %}br
|{% for pr in providers %}
a href=javascript:set_openid({{pr.url}}, {{pr.name}});{{pr.name}}/a |
{% endfor %}
/p
p{{form.remember_me}} Remember Me/p
pinput type=submit value=Sign In/p
/form
{% endblock %}
这次的模板添加的东西似乎有点多。一些公共账号需要提供用户名,为了解决这个我们用了点 javascript。当用户点击相关的公共账号链接时,需要用户名的公共账号会提示用户输入用户名, javascript 会把用户名处理成可用的公共账号,最后再插入到 openid 字段的文本框中。
下面这个是在登录页面点击 google 链接后显示的截图:
⑶ 在Python中使用HTML模版的教程
这篇文章主要介绍了在Python中使用HTML模版的教程,HTML模版也是Python的各大框架下的一个基本功能,需要的朋友可以参考下。Web框架把我们从WSGI中拯救出来了。现在,我们只需要不断地编写函数,带上URL,就可以继续Web App的开发了。
但是,Web App不仅仅是处理逻辑,展示给用户的页面也非常重要。在函数中返回一个包含HTML的字符串,简单的页面还可以,但是,想想新浪首页的6000多行的HTML,你确信能在Python的字符串中正确地写出来么?反正我是做不到。
俗话说得好,不懂前端的Python工程师不是好的产品经理。有Web开发经验的同学都明白,Web App最复杂的部分就在HTML页面。HTML不仅要正确,还要通过CSS美化,再加上复杂的JavaScript脚本来实现各种交互和动画效果。总之,生成HTML页面的难度很大。
由于在Python代码里拼字符串是不现实的,所以,模板技术出现了。
使用模板,我们需要预先准备一个HTML文档,这个HTML文档不是普通芹腔的HTML,而是嵌入了一些变量和指令,然后,根据我们传入的数据,替换后嫌嫌衫,得到最终的HTML,发送给用户:
这就是传说中的MVC:Model-View-Controller,中文名“模型-视图-控制器”。
Python处理URL的函数就是C:Controller,Controller负责业务逻辑,比如检查用户名是否存在,取出用户信息等等;
包含变量{{ name }}的模板就是V:View,View负责显示逻者枝辑,通过简单地替换一些变量,View最终输出的就是用户看到的HTML。
MVC中的Model在哪?Model是用来传给View的,这样View在替换变量的时候,就可以从Model中取出相应的数据。
上面的例子中,Model就是一个dict:
{ name: Michael }
只是因为Python支持关键字参数,很多Web框架允许传入关键字参数,然后,在框架内部组装出一个dict作为Model。
现在,我们把上次直接输出字符串作为HTML的例子用高端大气上档次的MVC模式改写一下:
16
17
18
19
20
21
22
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route(/, methods=[GET, POST])
def home():
return render_template(home.html)
@app.route(/signin, methods=[GET])
def signin_form():
return render_template(form.html)
@app.route(/signin, methods=[POST])
def signin():
username = request.form[username]
password = request.form[password]
if username==admin and password==password:
return render_template(signin-ok.html, username=username)
return render_template(form.html, message=Bad username or password, username=username)
if __name__ == __main__:
app.run()
Flask通过render_template()函数来实现模板的渲染。和Web框架类似,Python的模板也有很多种。Flask默认支持的模板是jinja2,所以我们先直接安装jinja2:
?
1
$ easy_install jinja2
然后,开始编写jinja2模板:
?
1
home.html
用来显示首页的模板:
11
html
head
titleHome/title
/head
body
h1 style=font-style:italicHome/h1
/body
/html
form.html
用来显示登录表单的模板:
16
17
18
html
head
titlePlease Sign In/title
/head
body
{% if message %}
p style=color:red{{ message }}/p
{% endif %}
form action=/signin method=post
legendPlease sign in:/legend
pinput name=username placeholder=Username value={{ username }}/p
pinput name=password placeholder=Password type=password/p
pbutton type=submitSign In/button/p
/form
/body
/html
signin-ok.html
登录成功的模板:
?
7
8
html
head
titleWelcome, {{ username }}/title
/head
body
pWelcome, {{ username }}!/p
/body
/html
登录失败的模板呢?我们在form.html中加了一点条件判断,把form.html重用为登录失败的模板。
最后,一定要把模板放到正确的templates目录下,templates和app.py在同级目录下:
启动python app.py,看看使用模板的页面效果:
通过MVC,我们在Python代码中处理M:Model和C:Controller,而V:View是通过模板处理的,这样,我们就成功地把Python代码和HTML代码最大限度地分离了。
使用模板的另一大好处是,模板改起来很方便,而且,改完保存后,刷新浏览器就能看到最新的效果,这对于调试HTML、CSS和JavaScript的前端工程师来说实在是太重要了。
在Jinja2模板中,我们用{{ name }}表示一个需要替换的变量。很多时候,还需要循环、条件判断等指令语句,在Jinja2中,用{% ... %}表示指令。
比如循环输出页码:
?
1
2
3
{% for i in page_list %}
a href=/page/{{ i }}{{ i }}/a
{% endfor %}
如果page_list是一个list:[1, 2, 3, 4, 5],上面的模板将输出5个超链接。
除了Jinja2,常见的模板还有:
Mako:用和${xxx}的一个模板;
Cheetah:也是用和${xxx}的一个模板;
Django:Django是一站式框架,内置一个用{% ... %}和{{ xxx }}的模板。
小结
有了MVC,我们就分离了Python代码和HTML代码。HTML代码全部放到模板里,写起来更有效率。
⑷ 使用python创建web静态网站
打开pyCharm企业版软件,创建一个Django项目,其中Django是一个Web框架,用于帮助开发交互式网站的工具。生成项目文件如下图所示:
在url.py文件中添加为:
在view.py文件中添加:
在templates文件夹中新建index.html文件
其中<a>为超链接标签,在此使用了一个模板标签,是用大括号和百分号({% %})表示的。{% url 'namespacename:index' %}是一个模板标签,指向url.py中index的URL模式匹配。在这个实例中,namespacename是对应的命名空间名称,index是URL模式。
⑸ Python 有哪些好的 Web 框架
1、Django框架
优点:是一个高层次Python Web开发框架,特点是开发快速、代码较少、可扩展性强。Django采用MTV(Model、Template、View)模型组织资源,框架功能丰富,模板扩展选择最多。对于专业人员来说,Django是当之无愧的Python排名第一的Web开发框架。
缺点:包括一些轻量级应用不需要的功能模块,不如Flask轻便。过度封装很多类和方法,直接使用比较简单,但改动起来比较困难。相比于 C,C++性能,Django性能偏低。模板实现了代码和样式完全分离,不允许模板里出现Python代码,灵活度不够。另外学习曲线也相对陡峭。
2、Flask框架
优点:Flask是一个Python Web开发的微框架,严格来说,它仅提供Web服务器支持,不提供全栈开发支持。然而,Flask非常轻量、非常简单,基于它搭建Web系统都以分钟来计时,特别适合小微原型系统的开发。花少时间、产生可用系统,是非常划算的选择。
缺点:对于大型网站开发,需要设计路由映射的规则,否则导致代码混乱。对新手来说,容易使用低质量的代码创建 “不良的web应用程序”。
3、Pyramid框架
优点:是一个扩展性很强且灵活的Python Web开发框架。上手十分容易,比较适合中等规模且边开发边设计的场景。Pyramid不提供绝对严格的框架定义,根据需求可以扩展开发,对高阶程序员十分友好。
缺点:国内知名度不高,高级用法需要通过阅读源代码获取灵感。默认使用Chameleon模板,灵活度没有成为一个要素。
4、web.py框架
优点:正如其名,web.py是一个采用Python作为开发语言的Web框架,简单且强大。俄罗斯排名第一的Yandex搜索引擎基于这个框架开发,Guido van Rossum认为这是最好的Python Web框架,还需要说别的吗?有事实作证、有大牛认可,用起来吧!
缺点:Web.py并未像其他框架一样保持与Python 3兼容性的最新状态。这不仅意味着缺乏对异步语法的支持,还意味着缺少对已弃用的函数的错误。此外,目前尚不清楚维护者是否有计划在Python 2到达其支持生命周期结束后保持Web.py的最新状态。
5、Tornado框架
优点:Tornado是一个基于异步网络功能库的Web开发框架,因此,它能支持几万个开放连接,Web服务高效稳定。可见,Tornado适合高并发场景下的Web系统,开发过程需要采用Tornado提供的框架,灵活性较差,确定场景后再考虑使用不迟。
缺点:Tornado 5.0改进了与Python的本机异步功能的集成。因此不再支持Python 3.3.并且Python 3.5用户必须使用Python 3.5.2或更高版本。Tornado 6.0将需要Python 3.5及更高版本,并将完全放弃Python 2支持。