在python的字元串中,有的符号要想表達其本意,需要在前面加上 \ \'單引号裡面\'
符号,例如單引号,如果要在字元串中表現它,必須寫成
樣式,才能實作一對單引号以及裡面的内容,否則,它就表示字元串了。
在HTML代碼中,也有類似的問題,比如
>
等,就是代碼的一部分,如果直接寫,就不會顯示在網頁裡,要想顯示,同樣需要轉義。另外,如果在網頁中有表單,總會有别有用心的人向表單中寫點包含 >
等字元的東西,目的就是要攻擊你的網站,為了防治邪惡之輩,也需要将使用者輸入的字元進行轉義,轉化為字元實體,讓它不具有HTML代碼的含義。 轉義字元串(Escape Sequence)也稱字元實體(Character Entity)。在HTML中,定義轉義字元串的原因有兩個:第一個原因是像“<”和“>”這類符号已經用來表示HTML标簽,是以就不能直接當作文本中的符号來使用。為了在HTML文檔中使用這些符号,就需要定義它的轉義字元串。當解釋程式遇到這類字元串時就把它解釋為真實的字元。在輸入轉義字元串時,要嚴格遵守字母大小寫的規則。第二個原因是,有些字元在ASCII字元集中沒有定義,是以需要使用轉義字元串來表示。
模闆自動轉義
Tornado 2 開始的模闆具有自動轉義的功能,這讓開發者省卻了不少事情。看一個例子。就利用上一講中建立的開發架構。要在首頁模闆中增加一個表單送出功能。
修改template/index.html檔案,内容如下:
<DOCTYPE html>
<html>
<head>
<title>Loop in template</title>
<link rel="stylesheet" type="text/css" href="{{ static_url('css/style.css')}}">
</head>
<body>
<h1>aaaAAA</h1>
<p>There is a list, it is <b>{{info}}</b></p>
<p>I will print the elements of this list in order.</p>
{% for element in info %}
<p>{{element}}</p>
{% end %}
<br>
{% for index,element in enumerate(info) %}
<p>info[{{index}}] is {{element}}
{% if element == "python" %}
<p> <b>I love this language--{{element}}</b></p>
{% end %}
{% end %}
{% if "[email protected]" in info %}
<p><b>A Ha, this the python lesson of hiekay, It is good! His email is {{info[2]}}</b></p>
{% end %}
<h2>Next, I set "python-tornado"(a string) to a variable(var)</h2>
{% set var="python-tornado" %}
<p>Would you like {{var}}?</p>
<!--增加表單-->
<form method="post" action="/option">
<p>WebSite:<input id="website" name="website" type="text"></p>
<p><input type="submit" value="ok,submit"></p>
</form>
</body>
</html>
在增加的表單中,要将内容以
post
方法送出到
"/option"
,是以,要在url.py中設定路徑,并且要建立相應的類。
然後就在handler目錄中建立一個新的檔案,命名為optform.py,其内容就是一個類,用來接收index.html中
post
過來的表單内容。
#!/usr/bin/env python
#coding:utf-8
import tornado.web
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
class OptionForm(tornado.web.RequestHandler):
def post(self):
website = self.get_argument("website") #接收名稱為'website'的表單内容
self.render("info.html",web=website)
為了達到接收表單post到上述類中内容的目的,還需要對url.py進行如下改寫:
#!/usr/bin/env python
#coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
from handler.index import IndexHandler
from handler.optform import OptionForm
url=[
(r'/', IndexHandler),
(r'/option', OptionForm),
]
還要注意,我在建立立的optform.py中,當接收到來自表單内容之後,就用另外一個模闆
info.html
顯示所接收到的内容。這個檔案放在template目錄中,代碼是:
<DOCTYPE html>
<html>
<head>
<title>Loop in template</title>
<link rel="stylesheet" type="text/css" href="{{ static_url('css/style.css')}}">
</head>
<body>
<h1>My Website is:</h1>
<p>{{web}}</p>
</body>
</html>
這樣我們就完成表單内容的送出和顯示過程。
從上面的流程中,是否體驗到這個架構的優勢了?不用重複敲代碼,隻需要在架構内的不同地方增加内容,即可完成網站。
示範運作效果:
我在表單中輸入了
<script>alert('bad script')</script>
,這是多麼陰險毒辣呀。
然而我們的tornado是不懼怕這種攻擊的,因為它的模闆自動轉義了。當點選按鈕送出内容的時候,就将那些陰險的符号實體化,成為轉義之後的符号了。于是就這樣了:
輸入什麼,就顯示什麼,不會因為輸入的内容含有陰險毒辣的符号而網站無法正常工作。這就是轉義的功勞。
不轉義的辦法
在tornado中,模闆實作了自動轉義,省卻了開發者很多事,但是,事情往往沒有十全十美的,這裡省事了,一定要在别的地方費事。例如在上面那個info.html檔案中,我打算在裡面加入我的電子信箱,但是要像下面代碼這樣,設定一個變量,主要是為了以後修改友善和在其它地方也可以随意使用。
<DOCTYPE html>
<html>
...(省略)
<body>
<h1>My Website is:</h1>
<p>{{web}}</p>
{% set email="<a href='mailto:[email protected]'>Connect to me</a>"%}
<p>{{email}}</p>
</body>
</html>
本來希望在頁面中出現的是
Connect to me
,點選它之後,就直接連接配接到發送電子郵件。結果,由于轉義,出現的是下面的顯示結果:
實作電子郵件超連結未遂。
這時候,就需要不讓模闆轉義。tornado提供的方法是:
- 在Application函數執行個體化的時候,設定參數:autoescape=None。這種方法不推薦使用,因為這樣就讓全站模闆都不轉義了,願意嘗試,不妨進行修改試一試,我這裡就不展示了。
- 在每個頁面中設定{% autoescape None %},表示這個頁面不轉義。也不推薦。
- 以上都不推薦,我推薦的是:{% raw email %},想讓哪裡不轉義,就在那裡用這種方式,比如要在email超級連結那裡不轉移,就寫成這樣好了。于是修改上面的代碼,看結果為:
<DOCTYPE html>
<html>
<head>
<title>Loop in template</title>
<link rel="stylesheet" type="text/css" href="{{ static_url('css/style.css')}}">
</head>
<body>
<h1>My Website is:</h1>
<p>{{web}}</p>
{%raw email="<a href='mailto:[email protected]'>Connect to me</a>"%}
</body>
</html>
如此,實作了不轉義。
以上都實作了模闆的轉義和不轉義。
url轉義
有些符号在URL中是不能直接傳遞的,如果要在URL中傳遞這些特殊符号,那麼就要使用它們的編碼了。編碼的格式為:%加字元的ASCII碼,即一個百分号%,後面跟對應字元的ASCII(16進制)碼值。例如 空格的編碼值是"%20"。
在python中,如果用utf-8寫了一段位址,如何轉義成url能夠接收的字元呢?
在python中有一個urllib子產品:
>>> import urllib
>>> #假設下面的url,是utf-8編碼
>>> url_mail='http://www.hiekay.com/[email protected]'
>>> #轉義為url能夠接受的
>>> urllib.quote(url_mail)
'http%3A//www.hiekay.com/email%3F%3Dhiekay%40gmail.com'
#反過來,一個url也能轉移為utf-8編碼格式,請用urllib.unquote()
>>>urllib.unquote('http%3A//www.hiekay.com/email%3F%3Dhiekay%40gmail.com')
'http://www.hiekay.com/[email protected]'
下面抄錄幫助文檔中的内容,供用到的朋友參考:
quote(s, safe='/')
quote('abc def') -> 'abc%20def'
Each part of a URL, e.g. the path info, the query, etc., has a
different set of reserved characters that must be quoted.
RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists
the following reserved characters.
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
"$" | ","
Each of these characters is reserved in some component of a URL,
but not necessarily in all of them.
By default, the quote function is intended for quoting the path
section of a URL. Thus, it will not encode '/'. This character
is reserved, but in typical usage the quote function is being
called on a path where the existing slash characters are used as
reserved characters.
unquote(s)
unquote('abc%20def') -> 'abc def'.
quote_plus(s, safe='')
Quote the query fragment of a URL; replacing ' ' with '+'
unquote_plus(s)
unquote('%7e/abc+def') -> '~/abc def'
轉義是網站開發中要特别注意的地方,不小心或者忘記了,就會糾結。