整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢(xún)熱線:

          在Django中使用Markdown

          為開(kāi)發(fā)人員,我們依賴(lài)于靜態(tài)分析工具來(lái)檢查、lint(分析)和轉(zhuǎn)換我們的代碼。我們使用這些工具來(lái)幫助我們提高生產(chǎn)效率并生成更好的代碼。然而,當(dāng)我們使用markdown編寫(xiě)內(nèi)容時(shí),可用的工具就很少。

          在本文中,我們將介紹如何開(kāi)發(fā)一個(gè)Markdown擴(kuò)展來(lái)解決在使用Markdown管理Django站點(diǎn)中的內(nèi)容時(shí)遇到的挑戰(zhàn)。

          你認(rèn)為他們有l(wèi)inter嗎?

          照片來(lái)自Pexels,由mali maeder拍攝

          問(wèn)題

          像每個(gè)網(wǎng)站一樣,我們?cè)谥黜?yè)、FAQ部分和“關(guān)于”頁(yè)面等地方都有不同類(lèi)型的(大部分)靜態(tài)內(nèi)容。很長(zhǎng)一段時(shí)間以來(lái),我們都是在Django模板中直接管理這些內(nèi)容的。

          當(dāng)我們最終決定是時(shí)候?qū)⑦@些內(nèi)容從模板轉(zhuǎn)移到數(shù)據(jù)庫(kù)中時(shí),我們認(rèn)為最好使用Markdown。從Markdown生成HTML更安全,它提供了一定程度的控制和一致性,并且對(duì)于非技術(shù)用戶(hù)來(lái)說(shuō)更容易處理。隨著我們轉(zhuǎn)移過(guò)程的進(jìn)展,我們注意到我們遺漏了一些東西:

          內(nèi)部鏈接

          當(dāng)URL更改時(shí),鏈接到內(nèi)部頁(yè)面的鏈接可能會(huì)中斷。在Django模板和視圖中,我們使用了reverseand {% url %},但是這在普通的Markdown中是不可用的。

          在不同環(huán)境之間進(jìn)行復(fù)制

          絕對(duì)內(nèi)部連接不能在不同環(huán)境之間進(jìn)行復(fù)制。這可以使用相對(duì)鏈接來(lái)解決,不過(guò)目前沒(méi)有開(kāi)箱即用的增強(qiáng)這一點(diǎn)的方法。

          無(wú)效鏈接

          無(wú)效鏈接會(huì)損害用戶(hù)體驗(yàn),并導(dǎo)致用戶(hù)質(zhì)疑整個(gè)內(nèi)容的可靠性。這并不是Markdown獨(dú)有的東西,只不過(guò)HTML模板是由對(duì)URL有一定了解的開(kāi)發(fā)人員維護(hù)的。另一方面,Markdown文檔是為非技術(shù)寫(xiě)作人員設(shè)計(jì)的。

          前期工作

          當(dāng)我研究這個(gè)問(wèn)題時(shí),我搜索了Python linters、Markdown預(yù)處理器和擴(kuò)展來(lái)幫助生成更好的Markdown。結(jié)果都不是很好。一個(gè)引人注目的方法是使用Django模板來(lái)生成Markdown文檔。

          使用Django模板預(yù)處理Markdown

          使用Django模板,你可以使用諸如url之類(lèi)的模板標(biāo)記來(lái)反向查詢(xún)URL名稱(chēng),并配合使用條件、變量、日期格式和所有其他Django模板特性。這種方法本質(zhì)上是使用Django模板作為Markdown文檔的預(yù)處理程序。

          我個(gè)人認(rèn)為這可能不是非技術(shù)作家的最佳解決方案。另外,我擔(dān)心提供對(duì)Django模板標(biāo)記的訪問(wèn)可能是危險(xiǎn)的。

          使用 Markdown

          對(duì)這個(gè)問(wèn)題有了更好的理解之后,我們準(zhǔn)備在Python中更深入地研究Markdown。

          將Markdown轉(zhuǎn)換為HTML

          要在Python中開(kāi)始使用Markdown,我們先安裝markdown包:

          接著,創(chuàng)建一個(gè)Markdown對(duì)象并使用其函數(shù)將一些Markdown轉(zhuǎn)換成HTML:

          你現(xiàn)在可以在你的模板中使用這個(gè)HTML代碼片段。

          使用Markdown擴(kuò)展

          基本的Markdown處理器提供了生成HTML內(nèi)容的基本要素。對(duì)于更“新奇”的選項(xiàng),Python markdown包包含了一些內(nèi)置擴(kuò)展。一個(gè)流行的擴(kuò)展是“extra”擴(kuò)展,除了其他東西之外,它增加了對(duì)隔離代碼塊的支持:

          為了使用我們獨(dú)特的Django功能擴(kuò)展Markdown,我們將開(kāi)發(fā)自己的擴(kuò)展。

          創(chuàng)建一個(gè)Markdown擴(kuò)展來(lái)處理內(nèi)聯(lián)鏈接

          如果你查看源代碼,你將看到要將markdown轉(zhuǎn)換為HTML, Markdown會(huì)使用多種不同的處理器。一種類(lèi)型的處理器是內(nèi)聯(lián)處理器。內(nèi)聯(lián)處理器會(huì)匹配特定的內(nèi)聯(lián)模式,如鏈接、反引號(hào)、粗體文本和帶下劃線的文本,并將它們轉(zhuǎn)換為HTML。

          我們的Markdown擴(kuò)展的主要目的是驗(yàn)證和轉(zhuǎn)換鏈接。因此,我們最感興趣的內(nèi)聯(lián)處理器是LinkInlineProcessor。這個(gè)處理器以[Haki的網(wǎng)站](https://hakibenito.com)的形式獲取markdown ,解析它并返回一個(gè)包含鏈接和文本的元組。

          為了擴(kuò)展該功能,我們擴(kuò)展了LinkInlineProcessor并創(chuàng)建了一個(gè)Markdown.Extension, 我們用它來(lái)處理鏈接:

          我們來(lái)將這段代碼分解一下::

          • DjangoUrlExtension擴(kuò)展注冊(cè)了一個(gè)名為DjangoLinkInlineProcessor的內(nèi)聯(lián)鏈接處理器。這個(gè)處理器將取代任何其他現(xiàn)有的鏈接處理器。

          • 內(nèi)聯(lián)處理器DjangoLinkInlineProcessor擴(kuò)展了內(nèi)置的LinkInlineProcessor,并在它處理的每個(gè)鏈接上調(diào)用clean_link函數(shù)。

          • clean_link函數(shù)接收一個(gè)鏈接和一個(gè)域名,并返回一個(gè)轉(zhuǎn)換后的鏈接。這就是我們要插入我們的實(shí)現(xiàn)的地方。

          如何獲得網(wǎng)站域名


          要識(shí)別到你自己網(wǎng)站的鏈接,你必須知道你的網(wǎng)站的域名。如果你正在使用Django的sites框架,那么你可以使用它來(lái)獲取當(dāng)前域名。


          我沒(méi)有把它包含在我的實(shí)現(xiàn)中,因?yàn)槲覀儧](méi)有使用sites框架。相反,我們?cè)贒jango設(shè)置中設(shè)置了一個(gè)變量。


          獲取當(dāng)前域名的另一種方法是使用HttpRequest對(duì)象。如果內(nèi)容只在你自己的站點(diǎn)中被編輯,你可以嘗試從請(qǐng)求對(duì)象中插入站點(diǎn)域名。這可能需要對(duì)你的實(shí)現(xiàn)進(jìn)行一些更改。

          要使用該擴(kuò)展,請(qǐng)?jiān)诔跏蓟粋€(gè)新的Markdown實(shí)例時(shí)添加它:

          太好了,這個(gè)擴(kuò)展已經(jīng)被使用了,我們準(zhǔn)備進(jìn)入有趣的部分了!

          驗(yàn)證和轉(zhuǎn)換Django鏈接

          既然我們得到了在所有鏈接上調(diào)用clean_link的擴(kuò)展,那我們可以來(lái)實(shí)現(xiàn)我們的驗(yàn)證和轉(zhuǎn)換邏輯。

          驗(yàn)證mailto鏈接

          要開(kāi)始工作,我們將從一個(gè)簡(jiǎn)單的驗(yàn)證開(kāi)始。mailto鏈接對(duì)于使用預(yù)定義的收件人地址、主題甚至消息正文打開(kāi)用戶(hù)的電子郵件客戶(hù)端非常有用。

          一個(gè)常見(jiàn)的mailto鏈接是這樣的:

          這個(gè)鏈接將打開(kāi)你的電子郵件客戶(hù)端,并設(shè)置成撰寫(xiě)一封主題行為“我需要幫助!”的新電子郵件給“support@service.com”。

          mailto鏈接不一定非要包含電子郵件地址。如果你看一看這篇文章底部的“分享”按鈕,你會(huì)發(fā)現(xiàn)像這樣的一個(gè)mailto鏈接:

          這個(gè)mailto鏈接沒(méi)有包含收件人,僅包含了主題行和消息正文。

          既然我們已經(jīng)很好地理解了mailto鏈接是什么樣子的,我們就可以向clean_link函數(shù)添加第一個(gè)驗(yàn)證:

          為了驗(yàn)證mailto鏈接,我們向clean_link中添加了以下代碼:

          • 檢查鏈接是否以mailto:開(kāi)頭,以識(shí)別相關(guān)鏈接。

          • 使用正則表達(dá)式將鏈接分割到它的組件。

          • 從mailto鏈接中刪除實(shí)際的電子郵件地址,并使用Django的EmailValidator驗(yàn)證它。

          注意,我們還添加了一種名為InvalidMarkdown的新異常類(lèi)型。我們定義了自己的自定義異常類(lèi)型,以將它與markdown本身所引發(fā)的其他錯(cuò)誤區(qū)分開(kāi)來(lái)。

          自定義錯(cuò)誤類(lèi)

          我曾經(jīng)寫(xiě)過(guò)關(guān)于自定義錯(cuò)誤類(lèi)的文章,為什么它們是有用的,以及你什么時(shí)候應(yīng)該使用它們。

          在我們繼續(xù)之前,讓我們添加一些測(cè)試,看看它的實(shí)際效果:

          太棒了!按預(yù)期的運(yùn)行了。

          處理內(nèi)部和外部鏈接

          既然我們已經(jīng)了解了mailto鏈接,我們也可以處理其他類(lèi)型的鏈接:

          外部鏈接

          • 我們的Django應(yīng)用程序外部的鏈接。

          • 必須包含一個(gè)頁(yè)面跳轉(zhuǎn)協(xié)議(scheme):http或https。

          • 理想情況下,我們還希望確保這些鏈接沒(méi)有被破壞,但我們現(xiàn)在不會(huì)這樣做。

          內(nèi)部鏈接

          • 到我們的Django應(yīng)用程序中的頁(yè)面的鏈接。

          • 鏈接必須是相對(duì)的:這將允許我們?cè)诓煌h(huán)境之間移動(dòng)內(nèi)容。

          • 使用Django的URL名稱(chēng)而不是一個(gè)URL路徑:這將允許我們安全地來(lái)回移動(dòng)視圖,而不必?fù)?dān)心markdown內(nèi)容中的失效鏈接。

          • 鏈接可能包含查詢(xún)參數(shù)(?)和片段(#)。

          SEO

          從SEO的角度來(lái)看,公共URL不應(yīng)該改變。當(dāng)他們這樣做的時(shí)候,你應(yīng)該使用重定向正確地處理它,否則你可能會(huì)受到搜索引擎的懲罰。

          有了這個(gè)需求列表,我們就可以開(kāi)始工作了。

          解析URL名稱(chēng)

          要鏈接到內(nèi)部頁(yè)面,我們希望編寫(xiě)者提供一個(gè)URL名稱(chēng),而不是URL路徑。例如,假設(shè)我們有這個(gè)視圖:

          這個(gè)頁(yè)面的URL路徑是https://example.com/, URL名稱(chēng)是home。我們想要在我們的markdown鏈接中使用這個(gè)URL名稱(chēng)home,就像這樣:

          這將渲染到:

          我們還想支持查詢(xún)參數(shù)和散列:

          這將渲染到以下HTML:

          在使用URL名稱(chēng)時(shí),如果我們更改了URL路徑,內(nèi)容中的鏈接將不會(huì)被破壞。要檢查作者提供的href是否是一個(gè)有效的url_name,我們可以嘗試reverse它:

          URL名稱(chēng)“home”指向URL路徑“/”。當(dāng)沒(méi)有匹配項(xiàng)時(shí),將會(huì)引發(fā)一個(gè)異常:

          在我們繼續(xù)之前,當(dāng)URL名稱(chēng)包含查詢(xún)參數(shù)或散列時(shí),會(huì)發(fā)生什么:

          這是有意義的,因?yàn)椴樵?xún)參數(shù)和散列不是URL名稱(chēng)的一部分。

          要使用reverse并支持查詢(xún)參數(shù)和散列,我們首先需要清除值。然后,檢查它是一個(gè)有效的URL名稱(chēng),并返回包含查詢(xún)參數(shù)和散列的URL路徑,如果提供了的話:

          這個(gè)代碼段使用一個(gè)正則表達(dá)式來(lái)以?或#的出現(xiàn)對(duì)href進(jìn)行分割,并返回各部分。

          請(qǐng)確保它可以工作:

          太了不起了!作者們現(xiàn)在可以在Markdown中使用URL名稱(chēng)了。它們還可以包括要添加到該URL的查詢(xún)參數(shù)和片段。

          處理外部鏈接

          要正確處理外部鏈接,我們需要檢查兩件事:

          1.外部鏈接總是提供一個(gè)跳轉(zhuǎn)協(xié)議,http:或者h(yuǎn)ttps:。

          2.阻止到我們自己網(wǎng)站的絕對(duì)鏈接。內(nèi)部鏈接應(yīng)該使用URL名稱(chēng)。

          到目前為止,我們已經(jīng)處理了URL名稱(chēng)和mailto鏈接。如果我們通過(guò)了這兩個(gè)檢查,這意味著href是一個(gè)URL。讓我們從檢查鏈接是否是鏈接到我們自己的網(wǎng)站開(kāi)始:

          函數(shù)urlparse會(huì)返回一個(gè)命名元組,該元組包含URL的不同部分。如果netloc屬性等于site_domain,那么該鏈接就確實(shí)是一個(gè)內(nèi)部鏈接。

          如果URL實(shí)際上是內(nèi)部的,我們就需要終止。但是,請(qǐng)記住,作者們不一定是技術(shù)人員,因此我們希望幫助他們,并提供一個(gè)有用的錯(cuò)誤消息。我們要求該內(nèi)部鏈接使用URL名稱(chēng)而不是URL路徑,所以最好讓作者們知道他們提供的路徑的URL名稱(chēng)。

          要獲得一個(gè)URL路徑的URL名稱(chēng),Django為我們提供了一個(gè)名為resolve的函數(shù):

          當(dāng)找到匹配項(xiàng)時(shí),resolve會(huì)返回一個(gè)ResolverMatch對(duì)象,其中包含URL名稱(chēng)和其他信息。當(dāng)沒(méi)有找到匹配項(xiàng)時(shí),它就會(huì)引發(fā)一個(gè)錯(cuò)誤:

          這實(shí)際上就是Django在底層所做的工作,用來(lái)確定在一個(gè)新請(qǐng)求到來(lái)時(shí)執(zhí)行哪個(gè)視圖函數(shù)。

          為了給作者們提供更好的錯(cuò)誤信息,我們可以使用來(lái)自ResolverMatch對(duì)象的URL名稱(chēng):

          當(dāng)我們識(shí)別出內(nèi)部鏈接時(shí),我們要處理兩種情況:

          • 我們沒(méi)有識(shí)別出這個(gè)URL:這個(gè)URL很可能是不正確的。請(qǐng)作者檢查該URL是否有錯(cuò)誤。

          • 我們識(shí)別出了這個(gè)URL: 這個(gè)URL是正確的,所以就告訴作者應(yīng)該使用什么URL名稱(chēng)。

          我們來(lái)實(shí)際地看一下它:

          漂亮!外部鏈接被接受,內(nèi)部鏈接被拒絕,并帶有一個(gè)有用的消息。

          要求跳轉(zhuǎn)協(xié)議

          我們要做的最后一件事是確保外部鏈接包含一個(gè)跳轉(zhuǎn)協(xié)議,要么是http:,要么是https:。讓我們將這最后一部分添加到函數(shù)clean_link:

          使用解析后的URL,我們可以很容易地檢查跳轉(zhuǎn)協(xié)議。讓我們確保它正在工作:

          我們向這個(gè)函數(shù)提供了一個(gè)沒(méi)有跳轉(zhuǎn)協(xié)議的鏈接,但是它運(yùn)行失敗了,并顯示了一條有用的消息。太酷了!

          整合代碼

          這是clean_link函數(shù)的全部代碼:

          要了解所有這些特性的一個(gè)實(shí)際用例是什么樣子的,請(qǐng)看下面的內(nèi)容:

          這將產(chǎn)生以下HTML:

          不錯(cuò)!

          結(jié)論

          我們現(xiàn)在有一個(gè)很不錯(cuò)的擴(kuò)展,它可以驗(yàn)證和轉(zhuǎn)換Markdown文檔中的鏈接!現(xiàn)在,在不同環(huán)境之間移動(dòng)文檔和保持內(nèi)容整潔要容易多了,最重要的是,可以保持正確和最新!

          源碼

          你可以在這個(gè)gist中找到全部源代碼。(地址:https://gist.github.com/hakib/73fccc340e855bb65f42197e298c0c7d )

          題外話

          本文中所描述的功能對(duì)我們很有用,但是你可能需要根據(jù)自己的需求對(duì)它進(jìn)行調(diào)整。

          如果你需要一些想法,那么除了這個(gè)擴(kuò)展之外,我們還創(chuàng)建了一個(gè)markdown Preprocessor,它允許作者們?cè)趍arkdown中使用常量。例如,我們定義了一個(gè)名為SUPPORT_EMAIL的常量,我們像這樣使用它:

          該預(yù)處理程序?qū)⒂梦覀兌x的文本替換字符串$SUPPORT_EMAIL,然后才渲染Markdown。

          英文原文:https://hakibenita.com/django-markdown
          譯者:Nothing

          者 | 單雨

          責(zé)編 | 胡巍巍

          出品 | CSDN(ID:CSDNnews)

          前言

          為了實(shí)現(xiàn)模板封裝和復(fù)用,提高HTML界面調(diào)試便捷性以及前后端解耦等目標(biāo),Django定義了自己的網(wǎng)絡(luò)模板語(yǔ)言。

          當(dāng)前介紹模板語(yǔ)言的官方文檔已經(jīng)非常完備,幾乎涵蓋了開(kāi)發(fā)中需要用到的知識(shí)點(diǎn)和需要注意的問(wèn)題,但同時(shí)官方文檔也存在一些問(wèn)題:

          • 翻譯不夠完善,帶來(lái)閱讀的困難;

          • 一些知識(shí)點(diǎn)的介紹過(guò)于簡(jiǎn)短,存在大量的頁(yè)內(nèi)鏈接,閱讀時(shí)需要跳轉(zhuǎn)到不同的頁(yè)面,閱讀不連貫。

          本文基于官方文檔系統(tǒng)介紹了Django模板語(yǔ)言的基礎(chǔ)知識(shí)點(diǎn),方便快速了解Django模板語(yǔ)言。

          模板系統(tǒng)設(shè)計(jì)哲學(xué)

          Django的模板系統(tǒng)不是簡(jiǎn)單的把Python嵌入到HTML中。

          它的設(shè)計(jì)宗旨是:模板系統(tǒng)旨在展示內(nèi)容, 而不是程序邏輯,因此不在HTML頁(yè)面中嵌入Python。

          簡(jiǎn)單的說(shuō),模板只負(fù)責(zé)渲染數(shù)據(jù),大多數(shù)邏輯應(yīng)該交給視圖(view)進(jìn)行處理。

          模板簡(jiǎn)介

          模板是一個(gè)簡(jiǎn)單的文本文件。它可以生成任何基于文本的格式(如 HTML,XML,CSV等)。除了基本的HTML標(biāo)簽外,模板還包含兩種額外的元素——變量和標(biāo)簽。

          模板中包含的變量可以被替換為變量的值,標(biāo)簽則被替換為相應(yīng)的模板控制邏輯。示例:

          django

          {% extends "base_generic.html" %}

          {% block title %}{{ section.title }}{% endblock %}

          {% block content %}

          <h1>{{ section.title }}</h1>

          {% for story in story_list %}

          <h2>

          <a href="{{ story.get_absolute_url }}">

          {{ story.headline|upper }}

          </a>

          </h2>

          <p>{{ story.tease|truncatewords:"100" }}</p>

          {% endfor %}

          {% endblock %}

          `{{ section.title }}`在模板渲染時(shí)將會(huì)被變量的值替換,for標(biāo)簽可以實(shí)現(xiàn)模板的循環(huán)渲染。

          基礎(chǔ)語(yǔ)法

          變量

          變量實(shí)現(xiàn)從模板上下文字典(返回HTTP響應(yīng)時(shí)傳遞過(guò)來(lái)的字典)中輸出一個(gè)值,這是一個(gè)類(lèi)似于dict的對(duì)象,包含鍵值對(duì)。當(dāng)模板引擎遇到一個(gè)變量時(shí),它會(huì)計(jì)算該變量,并用結(jié)果替換它。

          變量名由字母、數(shù)字字符和下劃線("_")組成,但不能以下劃線開(kāi)頭。點(diǎn)(".")也出現(xiàn)在變量中,代表屬性調(diào)用,變量名中不能有空格或標(biāo)點(diǎn)符號(hào)。

          示例:

          django

          My first name is {{ first_name }}. My last name is {{ last_name }}.

          當(dāng)傳入一個(gè)上下文字典`{'first_name': 'John', 'last_name': 'Doe'}`時(shí),將會(huì)渲染得到:

          django

          My first name is John. My last name is Doe.

          模板中的變量被字典中的值替換了。

          變量還可以使用點(diǎn)表示法實(shí)現(xiàn)字典查找、屬性查找和列表索引查找等操作:

          django

          {{ my_dict.key }}

          {{ my_object.attribute }}

          {{ my_list.0 }}

          點(diǎn)表示法底層原理

          當(dāng)模板系統(tǒng)遇到一個(gè)點(diǎn),它會(huì)按順序嘗試下面的動(dòng)作:

          1. 字典查詢(xún)

          2. 屬性或方法查找

          3. 數(shù)字索引查詢(xún)

          如果結(jié)果值是可調(diào)用的,則調(diào)用該值時(shí)將不帶參數(shù),調(diào)用的結(jié)果成為新的模板值。

          當(dāng)進(jìn)行能覆蓋字典查找的操作時(shí),這種查找順序可能會(huì)造成一些意想不到的行為。例如:如果試圖循環(huán)一個(gè)collection .defaultdict字典對(duì)象:

          django

          {% for k, v in defaultdict.items %}

          {其他操作}

          {% endfor %}

          因?yàn)樽值洳檎沂鞘紫劝l(fā)生的,所以這個(gè)行為會(huì)先提供一個(gè)默認(rèn)值,而不是使用預(yù)期的.items方法。在這種情況下,應(yīng)該首先考慮使用字典查找,而不是使用字典的屬性調(diào)用。

          注意

          屬性通常被解釋為一個(gè)文本字符串,防止和同名的變量沖突。例如{{foo.bar}}中的屬性“bar”將被解釋為一個(gè)文本字符串,如果模板上下文中存在變量“bar”,則不會(huì)使用該變量的值。

          以下劃線開(kāi)頭的變量屬性可能不能訪問(wèn),因?yàn)樗鼈兺ǔ1徽J(rèn)為是私有的。

          如果引用不存在的變量,模板系統(tǒng)將插入string_if_invalid選項(xiàng)的值,該選項(xiàng)默認(rèn)設(shè)置為“”(空字符串)。

          標(biāo)簽

          標(biāo)簽在模板渲染過(guò)程中提供任意邏輯。標(biāo)簽可以輸出內(nèi)容,作為控制結(jié)構(gòu),例如“if”語(yǔ)句或“for”循環(huán),從數(shù)據(jù)庫(kù)獲取內(nèi)容,甚至允許訪問(wèn)其他模板標(biāo)簽。

          (1)標(biāo)簽聲明

          標(biāo)簽的一般形式為:

          django

          {% tag %}

          示例:

          django

          {% csrf_token %}

          (2)傳入?yún)?shù)

          django

          {% cycle 'odd' 'even' %}

          (3)成對(duì)使用的標(biāo)簽

          有些標(biāo)簽需要開(kāi)始和結(jié)束標(biāo)簽:

          django

          {% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}

          (4)常用標(biāo)簽

          for:循環(huán)數(shù)組中的每個(gè)元素. 比如, 顯示列表 `athlete_list` 中每個(gè)元素的 `name` 屬性。

          django

          <ul>

          {% for athlete in athlete_list %}

          <li>{{ athlete.name }}</li>

          {% endfor %}

          </ul>

          if 、elif和else:在上面,如果athlete_list不為空,則{{athlete_list|length}}變量將顯示運(yùn)動(dòng)員的數(shù)量。

          否則,如果athlete_in_locker_room_list不為空,則會(huì)顯示“Athletes should be out…”消息。如果兩個(gè)列表都為空,則顯示“No athletes”。

          也可以在if標(biāo)簽里使用過(guò)濾器和各種操作符:

          django

          {% if athlete_list|length > 1 %}

          Team: {% for athlete in athlete_list %} ... {% endfor %}

          {% else %}

          Athlete: {{ athlete_list.0.name }}

          {% endif %}

          注意

          雖然上面的示例可以工作,但是要注意,大多數(shù)模板過(guò)濾器都返回字符串,因此使用過(guò)濾器進(jìn)行數(shù)學(xué)比較通常不會(huì)正常工作,而長(zhǎng)度是個(gè)例外。

          (5)更多

          Django有很多內(nèi)置標(biāo)簽,更多關(guān)于內(nèi)置標(biāo)簽的信息請(qǐng)參考官方文檔:

          https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/ref-templates-builtins-tags

          如果需要編寫(xiě)自定義標(biāo)簽,請(qǐng)參考官方文檔

          https://docs.djangoproject.com/zh-hans/2.2/howto/custom-template-tags/howto-writing-custom-template-tags

          如果需要對(duì)使用的標(biāo)簽和自定義的標(biāo)簽做一份說(shuō)明文檔,可以使用Django提供的文檔工具,詳情請(qǐng)參考:

          https://docs.djangoproject.com/zh-hans/2.2/ref/contrib/admin/admindocs/

          過(guò)濾器

          簡(jiǎn)介

          過(guò)濾器可以對(duì)變量做一些操作,例如給變量賦值,改變變量的值等。

          修改變量顯示

          過(guò)濾器可以修改變量的顯示。例如:

          django

          {{ name|lower }}

          通過(guò)過(guò)濾器lower變量{{ name }}變?yōu)榱诵?xiě)字符,通過(guò)管道符(|)間隔變量和過(guò)濾器來(lái)使用過(guò)濾器。

          鏈?zhǔn)秸{(diào)用過(guò)濾器

          一個(gè)過(guò)濾器的輸出可以作為下一個(gè)過(guò)濾器的輸入。

          {{ text|escape|linebreaks }}是一種常用的轉(zhuǎn)換方式, 在這之后換行符被替換為了 <p> 標(biāo)簽。

          轉(zhuǎn)換變量和標(biāo)簽參數(shù)

          過(guò)濾器轉(zhuǎn)換變量和標(biāo)簽參數(shù)的值。示例:

          django

          {{ django|title }}

          傳入`{'django': 'the web framework for perfecalist With deadline '}`上下文字典時(shí),該模板呈現(xiàn)為:

          django

          The Web Framework For Perfectionists With Deadlines

          傳入?yún)?shù)給過(guò)濾器

          示例1:

          django

          {{ my_date|date:"Y-m-d" }}

          my_date將會(huì)被替換為當(dāng)前日期。

          示例2:

          django

          {{ bio|truncatewords:30 }}

          將會(huì)會(huì)顯示 `bio` 變量的前30個(gè)字符

          注意

          過(guò)濾器參數(shù)中如果包含空格和標(biāo)點(diǎn)符號(hào),必須使用引號(hào)“”括起來(lái),例如,要用逗號(hào)和空格連接列表,可以使用{{list|join:", "}}。

          Django提供了大約60個(gè)內(nèi)置模板過(guò)濾器,請(qǐng)參考官方文檔:

          https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/ref-templates-builtins-filters

          下面列舉一些常用的過(guò)濾器:

          default

          如果變量為false或空,則使用給定的默認(rèn)值。否則,使用變量的值。例如:

          django

          {{ value|default:"nothing" }}

          如果 `value` 沒(méi)有提供或者為空,那么將它顯示為 "`nothing`" 。

          length

          返回值的長(zhǎng)度。這對(duì)字符串和列表都適用。例如:

          django

          {{ value|length }}

          如果 `value` 為 `['a', 'b', 'c', 'd']`, 那么他將被顯示為 `4`。

          filesizeformat

          將值格式化為“人類(lèi)可讀的”文件大小(即“13kb”、“4.1 MB”、“102字節(jié)”等)。例如:

          django

          {{ value|filesizeformat }}

          如果值為123456789,則輸出為117.7 MB。

          如果需要自定義過(guò)濾器,請(qǐng)參考請(qǐng)官方文檔:

          https://docs.djangoproject.com/zh-hans/2.2/howto/custom-template-tags/

          注釋

          示例:

          單行注釋

          django

          { this won't be rendered }

          多行注釋?zhuān)簕% comment %} 和{% endcomment %}

          django

          <p>Rendered text with {{ pub_date|date:"c" }}</p>

          {% comment "Optional note" %}

          <p>Commented out text with {{ create_date|date:"c" }}</p>

          {% endcomment %}

          注意:Comment標(biāo)簽不能嵌套使用。

          作者簡(jiǎn)介:?jiǎn)斡辏?0后工科男,偽文藝青年。目前就讀于北京理工大學(xué)宇航系,喜歡研究AI,網(wǎng)絡(luò)爬蟲(chóng),微信小程序以及機(jī)器人,癡迷于Coding,睡前必?cái)]碼。

          【END】

          兩天被django折磨的快崩潰了。要做一個(gè)網(wǎng)頁(yè),結(jié)果CSS 和圖片總是加載不出來(lái)。官方文檔中教了一部分,上網(wǎng)看樂(lè)各種教程都不行,研究了好幾個(gè)小時(shí),東拼西湊各個(gè)地方學(xué)一點(diǎn),終于弄出來(lái)了,趕緊記錄下來(lái)。

          django用的靜態(tài)文件路徑:STATICFILES_DIRS部署的方式,文件路徑一定要設(shè)置好。

          注: python2.7 django1.10.6; 項(xiàng)目mysite,項(xiàng)目下有一個(gè)應(yīng)用myapp

          一、目錄結(jié)構(gòu):

          整個(gè)目錄結(jié)構(gòu)是這樣的:

          | mysite

          | —— manage.py

          | —— mysite

          | —— | —— settings

          | —— | ——…(urls等)

          | —— templates

          | —— myapp

          | —— …(views等)

          | —— | —— templates

          | —— | —— | —— myapp

          | —— | —— | —— | —— home.html

          | —— | —— | —— | —— static

          | —— | —— | —— | —— | —— css

          | —— | —— | —— | —— | —— images

          注意,文件夾結(jié)構(gòu)比較復(fù)雜。

          在項(xiàng)目文件夾下有一個(gè)templates文件夾,不過(guò)這個(gè)文件夾暫時(shí)沒(méi)什么用,可以不用管(我也不知道為什么要有這么個(gè)文件夾)。

          應(yīng)用文件夾結(jié)構(gòu)是這樣的:

          “myapp/templates/myapp/home.html”;

          “myapp/templates/myapp/static/images”;

          “myapp/templates/myapp/static/CSS”;

          二、設(shè)置templates和靜態(tài)路徑

          • 在settings.py中設(shè)置templates路徑

          TEMPLATES = [

          {

          'BACKEND': 'django.template.backends.django.DjangoTemplates',

          'DIRS': [os.path.join(BASE_DIR, 'myapp/templates').replace('\', '/'),

          os.path.join(BASE_DIR, 'templates').replace('\', '/')],

          }

          ]

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 在settings.py文件的最后加上以下內(nèi)容:

          STATIC_ROOT = os.path.join(BASE_DIR, 'myapp/templates/myapp/static').replace('\', '/')

          STATICFILES_DIRS = (

          ('css', os.path.join(STATIC_ROOT, 'css').replace('\', '/')),

          ('images', os.path.join(STATIC_ROOT, 'images').replace('\', '/')),

          )

          • 1
          • 2
          • 3
          • 4
          • 5

          三、修改urls.py文件

          在urls.py開(kāi)頭加上一句:

          from django.contrib.staticfiles.urls import staticfiles_urlpatterns

          • 1

          在urls.py的最后加上以下內(nèi)容:

          #設(shè)置靜態(tài)文件路徑

          urlpatterns += staticfiles_urlpatterns()

          • 1
          • 2

          四、修改html文件

          home.html文件相關(guān)內(nèi)容如下:

          <!DOCTYPE html>

          <html lang="en">

          <head>

          <link href="/static/css/style.css" rel="stylesheet" type="text/css" />

          <title>Home</title>

          </head>

          <body>

          <a href="https://www.baidu.com/>

          <img src="/static/images/logo.png" alt="logo"/>

          </a>

          </body>

          </html>

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12

          改成自己的圖片名稱(chēng),注意圖片和link的前綴:/static/images/ 別寫(xiě)成 static/images/ ,這樣會(huì)無(wú)法顯示。

          感覺(jué)自己底子真的太差,這幾天一點(diǎn)一點(diǎn)看官方文檔感到非常吃力,很多地方都不懂,想直接看自己需要的部分又不知道該看哪。


          主站蜘蛛池模板: 国模精品视频一区二区三区| 国精产品一区一区三区有限公司| 国产伦精品一区二区三区免.费| 亚洲日本一区二区三区在线不卡| 精品国产日韩亚洲一区91| 色偷偷av一区二区三区| 中文字幕在线精品视频入口一区| 亚洲一区二区精品视频| 性色av无码免费一区二区三区 | 精品福利一区二区三区| 伊人精品视频一区二区三区| 精品日本一区二区三区在线观看 | 国产精品美女一区二区| 男人免费视频一区二区在线观看 | 日韩精品一区二区三区影院| 亚洲AV永久无码精品一区二区国产| 四虎成人精品一区二区免费网站| 亲子乱av一区二区三区| 国产观看精品一区二区三区| 久久99精品波多结衣一区| 无码日本电影一区二区网站| 久久国产高清一区二区三区| 蜜桃视频一区二区三区在线观看 | 91大神在线精品视频一区| 国产成人无码aa精品一区| 台湾无码一区二区| 亚洲国产成人久久综合一区77| 无码AV中文一区二区三区| 在线观看国产区亚洲一区成人| 久久无码AV一区二区三区| 97久久精品午夜一区二区| 精品一区二区三区影院在线午夜 | 精品一区二区三区| 一区二区中文字幕| 国产成人片视频一区二区| 国产精品福利一区| 精品国产一区二区三区香蕉事| 久久se精品一区二区国产| 国偷自产一区二区免费视频| 香蕉视频一区二区| 中文字幕一区二区免费|