python 網(wǎng)站 模板轉(zhuǎn)義

在python的字符串中,有的符號(hào)要想表達(dá)其本意,需要在前面加上\符號(hào),例如單引號(hào),如果要在字符串中表現(xiàn)它,必須寫(xiě)成\'單引號(hào)里面\'樣式,才能實(shí)現(xiàn)一對(duì)單引號(hào)以及里面的內(nèi)容,否則,它就表示字符串了。

在HTML代碼中,也有類似的問(wèn)題,比如>等,就是代碼的一部分,如果直接寫(xiě),就不會(huì)顯示在網(wǎng)頁(yè)里,要想顯示,同樣需要轉(zhuǎn)義。另外,如果在網(wǎng)頁(yè)中有表單,總會(huì)有別有用心的人向表單中寫(xiě)點(diǎn)包含>等字符的東西,目的就是要攻擊你的網(wǎng)站,為了防治邪惡之輩,也需要將用戶輸入的字符進(jìn)行轉(zhuǎn)義,轉(zhuǎn)化為字符實(shí)體,讓它不具有HTML代碼的含義。

轉(zhuǎn)義字符串(Escape Sequence)也稱字符實(shí)體(Character Entity)。在HTML中,定義轉(zhuǎn)義字符串的原因有兩個(gè):第一個(gè)原因是像“<”和“>”這類符號(hào)已經(jīng)用來(lái)表示HTML標(biāo)簽,因此就不能直接當(dāng)作文本中的符號(hào)來(lái)使用。為了在HTML文檔中使用這些符號(hào),就需要定義它的轉(zhuǎn)義字符串。當(dāng)解釋程序遇到這類字符串時(shí)就把它解釋為真實(shí)的字符。在輸入轉(zhuǎn)義字符串時(shí),要嚴(yán)格遵守字母大小寫(xiě)的規(guī)則。第二個(gè)原因是,有些字符在ASCII字符集中沒(méi)有定義,因此需要使用轉(zhuǎn)義字符串來(lái)表示。

模板自動(dòng)轉(zhuǎn)義

Tornado 2 開(kāi)始的模板具有自動(dòng)轉(zhuǎn)義的功能,這讓開(kāi)發(fā)者省卻了不少事情。看一個(gè)例子。就利用上一講中建立的開(kāi)發(fā)框架。要在首頁(yè)模板中增加一個(gè)表單提交功能。

修改template/index.html文件,內(nèi)容如下:

<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 "hiekay@gmail.com" 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>

在增加的表單中,要將內(nèi)容以post方法提交到"/option",所以,要在url.py中設(shè)置路徑,并且要建立相應(yīng)的類。

然后就在handler目錄中建立一個(gè)新的文件,命名為optform.py,其內(nèi)容就是一個(gè)類,用來(lái)接收index.html中post過(guò)來(lái)的表單內(nèi)容。

#!/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'的表單內(nèi)容
        self.render("info.html",web=website)

為了達(dá)到接收表單post到上述類中內(nèi)容的目的,還需要對(duì)url.py進(jìn)行如下改寫(xiě):

#!/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中,當(dāng)接收到來(lái)自表單內(nèi)容之后,就用另外一個(gè)模板info.html顯示所接收到的內(nèi)容。這個(gè)文件放在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>

這樣我們就完成表單內(nèi)容的提交和顯示過(guò)程。

從上面的流程中,是否體驗(yàn)到這個(gè)框架的優(yōu)勢(shì)了?不用重復(fù)敲代碼,只需要在框架內(nèi)的不同地方增加內(nèi)容,即可完成網(wǎng)站。

演示運(yùn)行效果:

我在表單中輸入了<script>alert('bad script')</script>,這是多么陰險(xiǎn)毒辣呀。

image.png

然而我們的tornado是不懼怕這種攻擊的,因?yàn)樗哪0遄詣?dòng)轉(zhuǎn)義了。當(dāng)點(diǎn)擊按鈕提交內(nèi)容的時(shí)候,就將那些陰險(xiǎn)的符號(hào)實(shí)體化,成為轉(zhuǎn)義之后的符號(hào)了。于是就這樣了:

image.png

輸入什么,就顯示什么,不會(huì)因?yàn)檩斎氲膬?nèi)容含有陰險(xiǎn)毒辣的符號(hào)而網(wǎng)站無(wú)法正常工作。這就是轉(zhuǎn)義的功勞。

不轉(zhuǎn)義的辦法

在tornado中,模板實(shí)現(xiàn)了自動(dòng)轉(zhuǎn)義,省卻了開(kāi)發(fā)者很多事,但是,事情往往沒(méi)有十全十美的,這里省事了,一定要在別的地方費(fèi)事。例如在上面那個(gè)info.html文件中,我打算在里面加入我的電子信箱,但是要像下面代碼這樣,設(shè)置一個(gè)變量,主要是為了以后修改方便和在其它地方也可以隨意使用。

<DOCTYPE html>
<html>
    ...(省略)
    <body>
    <h1>My Website is:</h1>
    <p>{{web}}</p>
    {% set email="<a href='mailto:hiekay@gmail.com'>Connect to me</a>"%}
    <p>{{email}}</p>
    </body>
</html>

本來(lái)希望在頁(yè)面中出現(xiàn)的是Connect to me,點(diǎn)擊它之后,就直接連接到發(fā)送電子郵件。結(jié)果,由于轉(zhuǎn)義,出現(xiàn)的是下面的顯示結(jié)果:

image.png

實(shí)現(xiàn)電子郵件超鏈接未遂。

這時(shí)候,就需要不讓模板轉(zhuǎn)義。tornado提供的方法是:

  • 在Application函數(shù)實(shí)例化的時(shí)候,設(shè)置參數(shù):autoescape=None。這種方法不推薦使用,因?yàn)檫@樣就讓全站模板都不轉(zhuǎn)義了,愿意嘗試,不妨進(jìn)行修改試一試,我這里就不展示了。
  • 在每個(gè)頁(yè)面中設(shè)置{% autoescape None %},表示這個(gè)頁(yè)面不轉(zhuǎn)義。也不推薦。
  • 以上都不推薦,我推薦的是:{% raw email %},想讓哪里不轉(zhuǎn)義,就在那里用這種方式,比如要在email超級(jí)鏈接那里不轉(zhuǎn)移,就寫(xiě)成這樣好了。于是修改上面的代碼,看結(jié)果為:
<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:hiekay@gmail.com'>Connect to me</a>"%}
    </body>
</html>
image.png

如此,實(shí)現(xiàn)了不轉(zhuǎn)義。

以上都實(shí)現(xiàn)了模板的轉(zhuǎn)義和不轉(zhuǎn)義。

url轉(zhuǎn)義

有些符號(hào)在URL中是不能直接傳遞的,如果要在URL中傳遞這些特殊符號(hào),那么就要使用它們的編碼了。編碼的格式為:%加字符的ASCII碼,即一個(gè)百分號(hào)%,后面跟對(duì)應(yīng)字符的ASCII(16進(jìn)制)碼值。例如 空格的編碼值是"%20"。

在python中,如果用utf-8寫(xiě)了一段地址,如何轉(zhuǎn)義成url能夠接收的字符呢?

在python中有一個(gè)urllib模塊:

>>> import urllib

>>> #假設(shè)下面的url,是utf-8編碼
>>> url_mail='http://www.hiekay.com/email?=hiekay@gmail.com'

>>> #轉(zhuǎn)義為url能夠接受的
>>> urllib.quote(url_mail)
'http%3A//www.hiekay.com/email%3F%3Dhiekay%40gmail.com'

#反過(guò)來(lái),一個(gè)url也能轉(zhuǎn)移為utf-8編碼格式,請(qǐng)用urllib.unquote()

>>>urllib.unquote('http%3A//www.hiekay.com/email%3F%3Dhiekay%40gmail.com')
'http://www.hiekay.com/email?=hiekay@gmail.com'

下面抄錄幫助文檔中的內(nèi)容,供用到的朋友參考:

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'

轉(zhuǎn)義是網(wǎng)站開(kāi)發(fā)中要特別注意的地方,不小心或者忘記了,就會(huì)糾結(jié)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容