整合營銷服務(wù)商

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

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

          Django框架學(xué)習(xí)筆記(五)URL頁面跳轉(zhuǎn)進(jìn)階及name屬性

          道Django某一個功能的用途,比單純地知道怎么用更有用。

          今天我們要學(xué)習(xí)的內(nèi)容是Django的頁面跳轉(zhuǎn),重點(diǎn)講的是使用url里的name參數(shù)

          一、給url設(shè)置name屬性

          1. 我想修改路徑名

          根據(jù)前面做好的web項目,登錄頁面的url為: http://127.0.0.1:8000/login/;如果我們想把路徑名login換成signin,該怎么做呢? 這時候我們就想到了在urls的urlpatterns里直接修改path路徑名,

          2. 遇到麻煩了

          如果views里對應(yīng)的方法有重定向跳轉(zhuǎn)就麻煩了,因為重定向跳轉(zhuǎn)的redirect方法里已經(jīng)寫了我們改名之前的路徑名。如果我們在url里將login改成signin,做了一次改名操作了,那么在views里我們還要再改一次。如果有很多個頁面都做了重定向到login頁面,我們就需要對每一個函數(shù)進(jìn)行修改操作,太麻煩了!有沒有什么辦法能讓我們做路徑修改的時候,只需要改一處就能搞定的呢?

          3. 解決方法:利用name屬性

          實(shí)際上Django給我們提供了URL的name屬性用來標(biāo)記url,我們可以在path中給指定路徑設(shè)置一個name屬性,

          urlpatterns = [
              path('signin/', app01_views.login, name="login"),
          ]

          在views中做重定向時不直接寫死路徑名,而是通過reverse('屬性名')反向查出前面的url,這樣修改路徑名就很方便了,直接修改path就可以了。

          return redirect(reverse('login'))

          通常情況下,我們是根據(jù)path里的路徑名,找到views里的方法,然后渲染頁面。而這里的重定向反轉(zhuǎn)操作是根據(jù)路徑名的name屬性,反向找到路徑的名稱。 這樣我們需要修改路徑名的時候,views里都不要動的,反正它找的是指定的名稱。name屬性規(guī)定好了之后,url路徑名想怎么改就怎么改。

          注意:使用反轉(zhuǎn)路徑名的方法,需要導(dǎo)入包from django.shortcuts import reverse。

          4. 如何使用URL的name屬性

          當(dāng)前階段我們主要用在兩處: 在View中使用redirect(reverse("login"))

          def index(request):
              username = request.GET.get('username')
              if username:
                  return render(request,'index.html')
              else:
                  return redirect(reverse('login'))

          在html中使用模板語言{% url 'login' %}

          <a href="{% url 'login'%}">登錄</a>

          5. 調(diào)用url的name時傳遞參數(shù)

          我們先復(fù)習(xí)一下url傳值的兩種常見方法:

          (1)直接使用url傳值

          以傳遞電影編號movie_id為例,如果想通過url傳值。在定義path的時候,使用path("movile_detail/<movie_id>",...),然后在views里定義方法來接收movie_id這個值,就定義成def movie_id(request,movie_id),瀏覽器中訪問的時候可以通過127.0.0.1:8000/movie_detail/8001就能把movie_id作為參數(shù)通過url傳過去。

          (2)使用查詢字符串傳值

          我們還是以傳遞電影編號為例,如果想通過url傳值。在定義path時,使用path("movie_detail/",...),在views里定義方法來接收就寫成

          def movie_id(request):
                  movie_id = request.GET.get(movie_id)

          在瀏覽器中訪問是,url需要輸入127.0.0.1:8000/?movie_id=8001。這樣也能完成url的傳值。

          (3)傳遞參數(shù)

          在views中,我們使用redirect重定向到一個新的url如果要傳遞參數(shù)該怎么辦呢? 有兩種方式:

          • 方式一: 使用tuple傳參數(shù),args=(''rico', '123')
          • 方式二: 使用dict傳參數(shù),kwargs={'username': 'rico', 'password': '123'}

          url設(shè)置如下:

          urlpatterns = [
              # 登錄url
              path('login/<username>/<password>',app01_views.login, name='login'),
          ]

          在views里定義login方法準(zhǔn)備接收兩個參數(shù):

          def login(request, username, password):
              return HttpResponse("用戶名:%s \t 密碼:%s" % (username, password))

          傳遞參數(shù)時:

          def index(request):
              username = request.GET.get('username')
              if username:
                  return HttpResponse('=== 這是首頁 ===')
              else:
                  return redirect(reverse('login', kwargs={'username': 'rico', 'password': '123'}))

          注意:是在reverse方法里添加參數(shù),傳的如果是元組則注意前后順序,如果是字典就不用考慮前后順序。

          如果要在templates中通過模板語言調(diào)用url的名稱, 模板語言里使用url傳遞參數(shù)可以寫成這樣:

          {% url 'login' username='xiaoyu' password='123' %}

          二、多app環(huán)境下URL的命名

          在多app項目中,如果各自的name屬性相同,在重定向訪問的時候會出現(xiàn)無法訪問指定app下的url的問題。這時候我們就在各自app的urls中添加命名空間

          app_name = 'app01'

          然后在重定向訪問指定url名稱的時候,添加命名空間屬性即可。

          def index(request):
              username = request.GET.get('username')
              if username:
                  return render(request, 'app01/index.html')
              else:
                  return redirect(reverse('app01:login'))

          注意:項目總體url配置使用include關(guān)鍵字,將多個app配置到總路由中。

          urlpatterns = [
              path('admin/', admin.site.urls),
              path('app01/', include('app01.urls')),
              path('app02/',include('app02.urls')),
          ]

          最后

          這一節(jié),我們主要介紹了Django中url路由跳轉(zhuǎn)的進(jìn)階知識,下一節(jié),我們將介紹Django下html頁面中的模板語言DTL,感謝大家的閱讀~

          求: 在views中返回的url需要返回到具體的某一篇文章的評論列表

          實(shí)現(xiàn)方式

          根據(jù)源碼得出:

          第一個參數(shù)就是使用的view方法

          第二個args參數(shù)可以傳入需要的參數(shù),比如文章的id。

          即可實(shí)現(xiàn)跳轉(zhuǎn)到指定文章。

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

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

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

          照片來自Pexels,由mali maeder拍攝

          問題

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

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

          內(nèi)部鏈接

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

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

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

          無效鏈接

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

          前期工作

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

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

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

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

          使用 Markdown

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

          將Markdown轉(zhuǎn)換為HTML

          要在Python中開始使用Markdown,我們先安裝markdown包:

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

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

          使用Markdown擴(kuò)展

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

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

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

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

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

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

          我們來將這段代碼分解一下::

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

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

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

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


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


          我沒有把它包含在我的實(shí)現(xiàn)中,因為我們沒有使用sites框架。相反,我們在Django設(shè)置中設(shè)置了一個變量。


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

          要使用該擴(kuò)展,請在初始化一個新的Markdown實(shí)例時添加它:

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

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

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

          驗證mailto鏈接

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

          一個常見的mailto鏈接是這樣的:

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

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

          這個mailto鏈接沒有包含收件人,僅包含了主題行和消息正文。

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

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

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

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

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

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

          自定義錯誤類

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

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

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

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

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

          外部鏈接

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

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

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

          內(nèi)部鏈接

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

          • 鏈接必須是相對的:這將允許我們在不同環(huán)境之間移動內(nèi)容。

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

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

          SEO

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

          有了這個需求列表,我們就可以開始工作了。

          解析URL名稱

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

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

          這將渲染到:

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

          這將渲染到以下HTML:

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

          URL名稱“home”指向URL路徑“/”。當(dāng)沒有匹配項時,將會引發(fā)一個異常:

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

          這是有意義的,因為查詢參數(shù)和散列不是URL名稱的一部分。

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

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

          請確保它可以工作:

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

          處理外部鏈接

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

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

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

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

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

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

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

          當(dāng)找到匹配項時,resolve會返回一個ResolverMatch對象,其中包含URL名稱和其他信息。當(dāng)沒有找到匹配項時,它就會引發(fā)一個錯誤:

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

          為了給作者們提供更好的錯誤信息,我們可以使用來自ResolverMatch對象的URL名稱:

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

          • 我們沒有識別出這個URL:這個URL很可能是不正確的。請作者檢查該URL是否有錯誤。

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

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

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

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

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

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

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

          整合代碼

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

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

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

          不錯!

          結(jié)論

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

          源碼

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

          題外話

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

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

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

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

          主站蜘蛛池模板: 一区二区高清在线| 日韩人妻无码一区二区三区久久99 | 国产精品久久久久一区二区三区| 日本一区二区三区精品视频| 国产内射999视频一区| 日本v片免费一区二区三区| 亚洲av日韩综合一区在线观看| 精品视频在线观看一区二区 | 人妻AV中文字幕一区二区三区| 精品91一区二区三区| 78成人精品电影在线播放日韩精品电影一区亚洲 | 99久久综合狠狠综合久久一区| chinese国产一区二区| 日本一区二区三区不卡在线视频| 无码日韩人妻av一区免费| 亚洲一区免费观看| 亚洲国产老鸭窝一区二区三区 | 国产一区二区好的精华液| 亚洲熟妇av一区| 3d动漫精品啪啪一区二区中文| 日本欧洲视频一区| 精品少妇一区二区三区视频| 中文字幕精品无码一区二区| 精品伦精品一区二区三区视频 | 无码人妻精品一区二区三区蜜桃| 国产一区二区三区在线2021| 中日av乱码一区二区三区乱码| 精品久久久久中文字幕一区| 国产成人片视频一区二区| 久久久久人妻精品一区三寸蜜桃| 亚洲福利精品一区二区三区| 一区二区三区www| 精品视频一区二区三区四区五区| 亚洲AV日韩精品一区二区三区| 乱人伦一区二区三区| 中文字幕在线无码一区二区三区| 国内国外日产一区二区| 日韩人妻不卡一区二区三区| 日本视频一区在线观看免费| 亚洲视频一区二区三区四区| 暖暖免费高清日本一区二区三区|