django——url(路由)配置

URL是Web服務的入口,用戶通過瀏覽器發送過來的任何請求,都是發送到一個指定的URL地址,然后被響應。

在Django項目中編寫路由,就是向外暴露我們接收哪些URL的請求,除此之外的任何URL都不被處理,也沒有返回。通俗地理解,不恰當的形容,URL路由是你的Web服務對外暴露的API。

Django奉行DRY主義,提倡使用簡潔、優雅的URL,沒有.php.cgi這種后綴,更不會單獨使用0、2097、1-1-1928、00這樣無意義的東西,讓你隨心所欲設計你的URL,不受框架束縛。

1. 概述


要設計應用程序的URL,可以創建一個非正式的稱為URLconf(URL配置)的Python模塊。此模塊是純Python代碼,是URL路徑表達式與Python函數(您的視圖)之間的映射。

該映射可以根據需要縮短或縮短。它可以引用其他映射。并且,因為它是純Python代碼,所以它可以動態構造。

Django還提供了一種根據活動語言翻譯URL的方法。

2. django如何處理請求

當用戶請求一個頁面時,Django根據下面的邏輯執行操作:

  1. 決定要使用的根URLconf模塊。通常,這是ROOT_URLCONF設置的值,但是如果傳入的HttpRequest對象具有urlconf屬性(由中間件設置),則其值將被用于代替ROOT_URLCONF設置。通俗的講,就是你可以自定義項目入口url是哪個文件!
  2. 加載該模塊并尋找可用的urlpatterns。?它是django.conf.urls.url()實例的一個列表。
  3. 依次匹配每個URL模式,在與請求的URL相匹配的第一個模式停下來。也就是說,url匹配是從上往下的短路操作,所以url在列表中的位置非常關鍵。
  4. 導入并調用匹配行中給定的視圖,該視圖是一個簡單的Python函數(被稱為視圖函數),或基于類的視圖。 視圖將獲得如下參數:
    1. 一個HttpRequest 實例。
    2. 如果匹配的正則表達式返回了沒有命名的組,那么正則表達式匹配的內容將作為位置參數提供給視圖。
    3. 關鍵字參數由正則表達式匹配的命名組組成,但是可以被django.conf.urls.url()的可選參數kwargs覆蓋。
  5. 如果沒有匹配到正則表達式,或者過程中拋出異常,將調用一個適當的錯誤處理視圖。

3. 轉換器

3.1 path轉換器

在django2.0 以上的版本中,默認使用的是path轉換器,我們首先以此舉例:

from django.urls import pathfrom . import viewsurlpatterns = [path('articles/2003/', views.special_case_2003),path('articles/<int:year>/', views.year_archive),path('articles/<int:year>/<int:month>/', views.month_archive),path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]

?

注意:

  1. 要捕獲一段url中的值,需要使用尖括號,而不是之前的圓括號;
  2. 可以轉換捕獲到的值為指定類型,比如例子中的int。默認情況下,捕獲到的結果保存為字符串類型,不包含/這個特殊字符;
  3. 匹配模式的最開頭不需要添加/,因為默認情況下,每個url都帶一個最前面的/,既然大家都有的部分,就不用浪費時間特別寫一個了。

匹配例子:

  • /articles/2005/03/ 將匹配第三條,并調用views.month_archive(request, year=2005, month=3);
  • /articles/2003/匹配第一條,并調用views.special_case_2003(request);
  • /articles/2003將一條都匹配不上,因為它最后少了一個斜杠,而列表中的所有模式中都以斜杠結尾;
  • /articles/2003/03/building-a-django-site/ 將匹配最后一個,并調用views.article_detail(request, year=2003, month=3, slug="building-a-django-site"

?

默認情況下,Django內置下面的路徑轉換器:

  • str:匹配任何非空字符串,但不含斜杠/,如果你沒有專門指定轉換器,那么這個是默認使用的;
  • int:匹配0和正整數,返回一個int類型
  • slug:可理解為注釋、后綴、附屬等概念,是url拖在最后的一部分解釋性字符。該轉換器匹配任何ASCII字符以及連接符和下劃線,比如’ building-your-1st-django-site‘;
  • uuid:匹配一個uuid格式的對象。為了防止沖突,規定必須使用破折號,所有字母必須小寫,例如’075194d3-6885-417e-a8a8-6c931e272f00‘ 。返回一個UUID對象;
  • path:匹配任何非空字符串,重點是可以包含路徑分隔符’/‘。這個轉換器可以幫助你匹配整個url而不是一段一段的url字符串。

3.2 re_path轉換器(老版的url)

Django2.0的url雖然改‘配置’了,但它依然向老版本兼容。而這個兼容的辦法,就是用re_path()方法代替path()方法。re_path()方法在骨子里,根本就是以前的url()方法,只不過導入的位置變了。下面是一個例子,對比一下Django1.11時代的語法,有什么太大的差別?

from django.urls import path, re_pathfrom . import viewsurlpatterns = [path('articles/2003/', views.special_case_2003),re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
]

?

path()方法不同的在于兩點:

  • year中匹配不到10000等非四位數字,這是正則表達式決定的
  • 傳遞給視圖的所有參數都是字符串類型。而不像path()方法中可以指定轉換成某種類型。在視圖中接收參數時一定要小心。

3.3 有名分組

上面的示例使用簡單的、沒有命名的正則表達式組(通過圓括號)來捕獲URL 中的值并以位置 參數傳遞給視圖。在更高級的用法中,可以使用命名的正則表達式組來捕獲URL 中的值并以關鍵字 參數傳遞給視圖。 在Python 正則表達式中,命名正則表達式組的語法是(?Ppattern),其中name 是組的名稱,pattern 是要匹配的模式。 下面是以上URLconf 使用命名組的重寫:

from django.urls import path,re_pathfrom app01 import viewsurlpatterns = [
re_path(r'^articles/2003/$', views.special_case_2003),
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]

?

這個實現與前面的示例完全相同,只有一個細微的差別:捕獲的值作為關鍵字參數而不是位置參數傳遞給視圖函數。例如:

/articles/2005/03/ 請求將調用views.month_archive(request, year='2005', month='03')函數,而不是views.month_archive(request, '2005', '03')。
/articles/2003/03/03/ 請求將調用函數views.article_detail(request, year='2003', month='03', day='03')。

?

3.4 路由分發

通常,我們會在每個app里,各自創建一個urls.py路由模塊,然后從根路由出發,將app所屬的url請求,全部轉發到相應的urls.py模塊中。

例如,下面是Django網站本身的URLconf節選。 它包含許多其它URLconf:

from django.conf.urls import include, urlurlpatterns = [# ... 忽略 ...re_path(r'^community/', include('django_website.aggregator.urls')),re_path(r'^contact/', include('django_website.contact.urls')),# ... 忽略 ...
]

?

路由轉發使用的是include()方法,需要提前導入,它的參數是轉發目的地路徑的字符串,路徑以圓點分割。

注意,這個例子中的正則表達式沒有包含$(字符串結束匹配符),但是包含一個末尾的斜杠。 每當Django 遇到include()(來自django.conf.urls.include())時,它會去掉URL中匹配的部分并將剩下的字符串發送給include的URLconf做進一步處理,也就是轉發到二級路由去。

另外一種轉發其它URL模式的方式是使用一個url()實例的列表。 例如,下面的URLconf:

from django.conf.urls import include, urlfrom apps.main import views as main_views
from credit import views as credit_viewsextra_patterns = [re_path(r'^reports/$', credit_views.report),re_path(r'^reports/(?P<id>[0-9]+)/$', credit_views.report),re_path(r'^charge/$', credit_views.charge),
]urlpatterns = [re_path(r'^$', main_views.homepage),re_path(r'^help/', include('apps.help.urls')),re_path(r'^credit/', include(extra_patterns)),
]

?

在此示例中,/credit/reports/URL將由credit_views.report()視圖處理。這種做法,相當于把二級路由模塊內的代碼寫到根路由模塊里一起了,不是很推薦。

再看下面的URLconf:

from django.conf.urls import url
from . import viewsurlpatterns = [re_path(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/history/$', views.history),re_path(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/edit/$', views.edit),re_path(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/discuss/$', views.discuss),re_path(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/permissions/$', views.permissions),
]

?

上面的路由寫得不好,我們可以改進它,只需要聲明共同的路徑前綴一次,并將后面的部分分組轉發:

from django.conf.urls import include, url
from . import viewsurlpatterns = [re_path(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([re_path(r'^history/$', views.history),re_path(r'^edit/$', views.edit),re_path(r'^discuss/$', views.discuss),re_path(r'^permissions/$', views.permissions),])),
]

?

這樣就優雅多了,也清爽多了,但前提是你要理解這種做法。

3.5 反向解析

在使用Django 項目時,一個常見的需求是獲得URL 的最終形式,以用于嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用于處理服務器端的導航(重定向等)。人們強烈希望不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 毫不相關的專門的URL 生成機制,因為這樣容易導致一定程度上產生過期的URL。 在需要URL 的地方,對于不同層級,Django 提供不同的工具用于URL 反查:

  1. 在模板中:使用url 模板標簽。
  2. 在Python 代碼中:使用from django.urls import reverse()函數 urls.py:
from django.conf.urls import urlfrom . import viewsurlpatterns = [
#...
re_path(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
#...
]

?

在模板中:

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a><ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>

?

在python中:

from django.urls import reverse
from django.http import HttpResponseRedirectdef redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse('news-year-archive', args=(year,))) # 同redirect("/path/")

?

當命名你的URL 模式時,請確保使用的名稱不會與其它應用中名稱沖突。如果你的URL 模式叫做comment,而另外一個應用中也有一個同樣的名稱,當你在模板中使用這個名稱的時候不能保證將插入哪個URL。在URL 名稱中加上一個前綴,比如應用的名稱,將減少沖突的可能。我們建議使用myapp-comment 而不是comment。

3.6 名稱空間

命名空間(英語:Namespace)是表示標識符的可見范圍。一個標識符可在多個命名空間中定義,它在不同命名空間中的含義是互不相干的。這樣,在一個新的命名空間中可定義任何標識符,它們不會與任何已有的標識符發生沖突,因為已有的定義都處于其它命名空間中。 由于name沒有作用域,Django在反解URL時,會在項目全局順序搜索,當查找到第一個name指定URL時,立即返回 我們在開發項目時,會經常使用name屬性反解出URL,當不小心在不同的app的urls中定義相同的name時,可能會導致URL反解錯誤,為了避免這種事情發生,引入了命名空間。

project的urls.py:

urlpatterns = [
re_path(r'^admin/', admin.site.urls),
re_path(r'^app01/', include("app01.urls",namespace="app01")),
re_path(r'^app02/', include("app02.urls",namespace="app02")),
]

?

app01.urls:

urlpatterns = [
re_path(r'^index/', index,name="index"),
]

?

app02.urls:

urlpatterns = [
re_path(r'^index/', index,name="index"),
]

?

app01.views

from django.core.urlresolvers import reverse
def index(request):
return HttpResponse(reverse("app01:index"))

?

app02.views

from django.core.urlresolvers import reverse
def index(request):
return HttpResponse(reverse("app02:index"))

?

?

?

轉載于:https://www.cnblogs.com/huang-yc/p/9651162.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/396845.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/396845.shtml
英文地址,請注明出處:http://en.pswp.cn/news/396845.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

VC連接mysql數據庫錯誤:libmysql.lib : fatal error LNK1113: invalid machine 解決方法

VC連接MySQL的配置過程在上一篇博文中&#xff0c;不過當你設置好&#xff0c;以為萬事大吉的時候&#xff0c;運行卻出現這個錯誤&#xff1a;libmysql.lib : fatal error LNK1113: invalid machine type。 無效的機器類型&#xff0c;真的是很讓人捉急。 發生這個錯誤的原因是…

linux 內存泄漏 定位,一種內存泄露檢查和定位的方法

一個系統后臺服務進程&#xff0c;可能包括多個線程&#xff0c;在生成環境下要求系統程序能夠穩定長時間穩定運行而不宕機。其中一個基本的前提就是需要保證系統程序不存在內存泄露。那么&#xff0c;該如何判讀系統程序是否存在內存泄露呢&#xff1f;如果存在&#xff0c;又…

python怎么發送郵件_在Python如何使用SMTP發送郵件

SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;即簡單郵件傳輸協議,它是一組用于由源地址到目的地址傳送郵件的規則&#xff0c;由它來控制信件的中轉方式。 python的smtplib提供了一種很方便的途徑發送電子郵件。它對smtp協議進行了簡單的封裝。 Python創建 SMTP…

統計單詞個數(劃分型)

codevs 1040 統計單詞個數 2001年NOIP全國聯賽提高組 題目等級 : 黃金 Gold題目描述 Description給出一個長度不超過200的由小寫英文字母組成的字母串(約定;該字串以每行20個字母的方式輸入&#xff0c;且保證每行一定為20個)。要求將此字母串分成k份(1<k<40)&#xff0c…

基于ASP.NET的新聞管理系統(三)代碼展示

5.1.1欄目部分 增加欄目&#xff08;addLanMu.aspx&#xff09;&#xff1a; <html xmlns"http://www.w3.org/1999/xhtml"> <head runat"server"> <title></title> <link rel"stylesheet" type"text/css" …

洛谷-求同構數的個數-NOIP2013提高組復賽

題目描述 Description 所謂同構數是指這樣的數&#xff0c;即它出現在它的平方數的右端。例如&#xff0c;5的平方是25 &#xff08;即5525&#xff09;&#xff0c;5是25右端的數&#xff0c;那么5就是同構數。又如&#xff0c;25的平方是625&#xff08;即2525625&#xff09…

plex linux 數據目錄,shareplex日常維護文檔

2017/07/25##SharePlex日常維護源(SRC)&#xff1a;192.168.1.101 db01目標(TGT):192.168.1.102 db02SRC:su - oraclesp_ctrlshowqstatusshow capture detailshow read detailshow log reverseshow config --查看當前使用參數文件list config --羅列出所有的參數文件(使用和未使…

ifconfig命令找不到_02. Linux命令之查看網絡連接

1. 查看網絡連接數和端口使用 netstat 命令查看網絡連接情況netstat -anp參數&#xff1a;-a 顯示所有選項-t (tcp)僅顯示tcp相關選項-u (udp)僅顯示udp相關選項-n 拒絕顯示別名&#xff0c;能顯示數字的全部轉化成數字。-p 顯示建立相關鏈接的程序名關鍵列解釋:Proto 表示協議…

grep與egrep的區別

grep與egrep的區別&#xff1b; 在linux系統環境下&#xff0c;我們通常使用grep命令來過濾出需要的行而egrep確很少使用&#xff0c;他們的區別其實很簡單&#xff0c;grep默認不支持正則表達式&#xff0c;egrep默認支持正則表達式&#xff0c;egrep 等于 grep -E 命令。轉載…

python學習之模塊(pip),列表生成式,模塊操作mysql,excel

python基礎 生成式 列表生成式  格式 [表達式 for 表達式 in 迭代對象 (可加判斷)] 原&#xff1a; 1 res1 [] 2 for i in range(1,5): 3   res1.append(i) 4 print(res1) 改&#xff1a; 1 res2 [i for i in range(1,5)] 2 print(res2) 字典生成式  格式 {key:value f…

linux驅動read函數 copytouser,Linux驅動編程 step-by-step (五)主要的文件操作方法實現...

主要的文件操作方法實現文件操作函數有很多的操作接口&#xff0c;驅動編程需要實現這些接口&#xff0c;在用戶編程時候系統調用時候會調用到這些操作structfile_operations {...loff_t (*llseek) (structfile *, loff_t,int);ssize_t (*read) (structfile *,char__user *,siz…

web開發中的 emmet 效率提升工具

web開發中的 emmet 效率提升工具 可以用來快速生成html 代碼。 并且給各種IDE、編輯器提供了插件支持&#xff0c;sublime &#xff0c;webstorm等。 如在webstorm中安裝好emmet之后&#xff0c;輸入以下文本&#xff0c; #page>div.content[ng-model"user"]ul>…

python二維數組操作_Python二維數組應用與操作

課課家將會在這里為大家詳細的介紹一下Python二維數組的相關應用方法以及定義方式&#xff0c;相信朋友們可以從中學習到更多的知識。 Python數組的應用中在實際編程中是一個非常重要的應用技術&#xff0c;作為Python編程人員來說&#xff0c;必須要熟練的掌握這方面的所有應用…

基于光線追蹤的渲染中景深(Depth of field)效果的實現

圖形學離線渲染中常用的透視攝像機模型時根據小孔成像的原理建立的&#xff0c;其實現通常是從向成像平面上發射ray&#xff0c;并把trace這條ray的結果作為成像平面上對應交點的采樣結果。即&#xff1a; 圖片來自《Fundamentals of Computer Graphics》 現實中的鏡頭拍攝的圖…

ubuntu 安裝 pycharm

添加源&#xff1a;$ sudo add-apt-repository ppa:mystic-mirage/pycharm安裝收費的專業版&#xff1a;$ sudo apt update$ sudo apt install pycharm安裝免費的社區版&#xff1a;$ sudo apt update$ sudo apt install pycharm-community卸載&#xff1a;$ sudo apt remove p…

帶你制作百詞斬單詞表讀寫插件

上篇博文簡單的介紹了一下Chrome插件&#xff0c;今天就與大家分享一下我做的這款有實際意義的插件吧。 做這款插件主要是用百詞斬站點進行單詞學習時&#xff0c;遇到的一點點鬧心事兒。在單詞表中不能聽發音。也不能練習拼寫。所以才忍無可忍的做了這么一款插件。自我感覺還是…

Linux7改運行級別,Centos7.0修改系統運行級別

首先翻譯下ininttab里面的內容&#xff1a;#inittab不再使用時利用系統。#添加配置這會對你的系統沒有影響。#Ctrl-Alt-Delete由/usr/lib系統/系統/ctrl-alt-del.target處理#系統使用的目標而不是運行級別。默認情況下&#xff0c;有兩個主要目標&#xff1a;#multi-user.targe…

python測試字符串類型的函數_python-02 數據類型 字符串str

字符串str 一、字符串定義 概念&#xff1a;字符串是有序的 不可修改的&#xff0c;元素以引號包圍的序列 引號類型&#xff1a;單引號 “”雙引號 “ ””三引號 三單引號 print(python) print("python") print(python) print("""python""…

POJ2115 C Looooops(線性同余方程)

無符號k位數溢出就相當于mod 2k&#xff0c;然后設循環x次A等于B&#xff0c;就可以列出方程&#xff1a; $$ CxA \equiv B \pmod {2^k} $$ $$ Cx \equiv B-A \pmod {2^k} $$ 最后就用擴展歐幾里得算法求出這個線性同余方程的最小非負整數解。 1 #include<cstdio>2 #incl…

工作測試博客

工作測試博客轉載于:https://blog.51cto.com/12559670/1895000