目錄html
路由與視圖函數對應關係 >>> 路由層前端
URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL與要爲該URL調用的視圖函數之間的映射表。python
你就是以這種方式告訴Django,對於這個URL調用這段代碼,對於那個URL調用那段代碼。nginx
基本格式:git
from django.conf.urls import url urlpatterns = [ url(正則表達式, views視圖函數,參數,別名), ]
注意:正則表達式
Django 2.0版本中的路由系統已經替換成下面的寫法(官方文檔):django
from django.urls import path urlpatterns = [ 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), ]
舉例:後端
from django.conf.urls import url from django.contrib import admin from app02 import views urlpatterns = [ url(r'^book_list/', views.book_list), url(r'test', views.test), url(r'test_add', views.test_add), ]
參數說明瀏覽器
注意服務器
^articles
而不是 ^/articles
。示例:
''' 一些請求的例子: /articles/2005/03/ 請求將匹配列表中的第三個模式。Django 將調用函數views.month_archive(request, '2005', '03')。 /articles/2005/3/ 不匹配任何URL 模式,由於列表中的第三個模式要求月份應該是兩個數字。 /articles/2003/ 將匹配列表中的第一個模式不是第二個,由於模式按順序匹配,第一個會首先測試是否匹配。請像這樣自由插入一些特殊的狀況來探測匹配的次序。 /articles/2003 不匹配任何一個模式,由於每一個模式要求URL 以一個反斜線結尾。 /articles/2003/03/03/ 將匹配最後一個模式。Django 將調用函數views.article_detail(request, '2003', '03', '03')。 '''
APPEND_SLASH:是否開啓URL訪問地址後面不爲/跳轉至帶有/的路徑的配置項
# 是否開啓URL訪問地址後面不爲/跳轉至帶有/的路徑的配置項 APPEND_SLASH=True
Django settings.py配置文件中默認沒有 APPEND_SLASH 這個參數,但 Django 默認這個參數爲 APPEND_SLASH = True。 其做用就是自動在網址結尾加'/'。
其效果就是:
咱們定義了urls.py:
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^blog/$', views.blog), ]
訪問 http://www.example.com/blog 時,默認將網址自動轉換爲 http://www.example/com/blog/ 。
若是在settings.py中設置了 APPEND_SLASH=False,此時咱們再請求 http://www.example.com/blog 時就會提示找不到頁面。
分組:給某一段正則表達式加括號
在使用Django 項目時,一個常見的需求是得到URL的最終形式,以用於嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用於處理服務器端的導航(重定向等)。
人們強烈但願不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 絕不相關的專門的URL 生成機制,由於這樣容易致使必定程度上產生過時的URL。
換句話講,須要的是一個DRY 機制。除了其它有點,它還容許設計的URL 能夠自動更新而不用遍歷項目的源代碼來搜索並替換過時的URL。
獲取一個URL 最開始想到的信息是處理它視圖的標識(例如名字),查找正確的URL 的其它必要的信息有視圖參數的類型(位置參數、關鍵字參數)和值。
Django 提供一個辦法是讓URL 映射是URL 設計惟一的地方。你填充你的URLconf,而後能夠雙向使用它:
第一種方式是咱們在前面的章節中一直討論的用法。第二種方式叫作反向解析URL、反向URL 匹配、反向URL 查詢或者簡單的URL 反查。
在須要URL 的地方,對於不一樣層級,Django 提供不一樣的工具用於URL 反查:
上面說了一大堆,你可能並無看懂。(那是官方文檔的生硬翻譯)。
我們簡單來講就是能夠給咱們的URL匹配規則起個名字,一個URL匹配模式起一個名字。
這樣咱們之後就不須要寫死URL代碼了,只須要經過名字來調用當前的URL。
舉個簡單的例子:
url(r'^home', views.home, name='home'), # 給個人url匹配模式起名爲 home url(r'^index/(\d*)', views.index, name='index'), # 給個人url匹配模式起名爲index
這樣:
在模板裏面能夠這樣引用:
{% url 'home' %}
在views函數中能夠這樣引用:
from django.urls import reverse reverse("index", args=("2018", ))
例子:
考慮下面的URLconf:
from django.conf.urls import url from . import views urlpatterns = [ # ... url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'), # ... ]
根據這裏的設計,某一年nnnn對應的歸檔的URL是/articles/nnnn/
。
你能夠在模板的代碼中使用下面的方法得到它們:
<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.shortcuts import redirect def redirect_to_year(request): # ... year = 2006 # ... return redirect(reverse('news-year-archive', args=(year,)))
若是出於某種緣由決定按年歸檔文章發佈的URL應該調整一下,那麼你將只須要修改URLconf 中的內容。
在某些場景中,一個視圖是通用的,因此在URL 和視圖之間存在多對一的關係。對於這些狀況,當反查URL 時,只有視圖的名字還不夠。
注意:
爲了完成上面例子中的URL 反查,你將須要使用命名的URL 模式。URL 的名稱使用的字符串能夠包含任何你喜歡的字符。不僅限制在合法的Python 名稱。
當命名你的URL 模式時,請確保使用的名稱不會與其它應用中名稱衝突。若是你的URL 模式叫作comment
,而另一個應用中也有一個一樣的名稱,當你在模板中使用這個名稱的時候不能保證將插入哪一個URL。
在URL 名稱中加上一個前綴,好比應用的名稱,將減小衝突的可能。咱們建議使用myapp-comment
而不是comment
。
urlpatterns = [ url(r'^test/(\d+)', views.test), ]
會將括號內匹配到的內容當作 位置參數 傳遞給後面的視圖函數
def test(request,args): print(args) return HttpResponse('test')
urlpatterns = [ url(r'^test/(?P<year>\d+)', views.test), ]
會將括號內匹配到的內容當作 關鍵字參數 傳遞給後面的視圖函數
方式1 # def test(request,**kwargs): # print(kwargs) # return HttpResponse('test') 方式2 def test(request,year): print(year,1) return HttpResponse('test')
url(r'^test/(\d+)/(\d+)/', views.test), url(r'^test/(?P<xxx>\d+)/(?P<month>\d+)/', views.test),
在使用Django 項目時,一個常見的需求是得到URL 的最終形式,以用於嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用於處理服務器端的導航(重定向等)。人們強烈但願不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 絕不相關的專門的URL 生成機制,由於這樣容易致使必定程度上產生過時的URL。
在須要URL 的地方,對於不一樣層級,Django 提供不一樣的工具用於URL 反查:
from django.urls import reverse()函數
根據某一個東西 動態解析出一個結果 該結果能夠直接訪問對應的url
url(r'^test_add/', views.testadd,name='xxx') 前端解析 {% url 'xxx' %} 後端解析 from django.shortcuts import render,HttpResponse,redirect,reverse url = reverse('xxx')
url(r'^test_addsajdsjkahdkjasjkdh/(\d+)/', views.testadd,name='xxx'),
前端解析 <a href="{% url 'xxx' 1 %}">222</a> 後端解析 url = reverse('xxx',args=(1,))
url(r'^test_addsajdsjkahdkjasjkdh/(?P<year>\d+)/', views.testadd,name='xxx')
前端解析 <a href="{% url 'xxx' 1 %}">222</a> <a href="{% url 'xxx' year=1 %}">222</a> 後端解析 url = reverse('xxx',args=(1,)) url = reverse('xxx',kwargs={'year':123})
注意 反向解析的別名 必定不要重複
django裏面的app能夠有本身的static文件,templates文件夾,urls.py(******) 項目名下面的urls.py再也不作路由與視圖函數對應關係 而是作一箇中轉站 只負責將請求分發到不一樣的app中 而後在app的urls.py完成路由與視圖函數的對應關係 from django.conf.urls import url,include url(r'^app01/',include(app01_urls)), url(r'^app02/',include(app02_urls))
命名空間(英語:Namespace)是表示標識符的可見範圍。一個標識符可在多個命名空間中定義,它在不一樣命名空間中的含義是互不相干的。這樣,在一個新的命名空間中可定義任何標識符,它們不會與任何已有的標識符發生衝突,由於已有的定義都處於其它命名空間中。
因爲name沒有做用域,Django在反解URL時,會在項目全局順序搜索,當查找到第一個name指定URL時,當即返回
咱們在開發項目時,會常用name屬性反解出URL,當不當心在不一樣的app的urls中定義相同的name時,可能會致使URL反解錯誤,爲了不這種事情發生,引入了命名空間。
解決各個app之間命名的重複 ,django是分不清楚。
總路由
url(r'^app01/',include('app01.urls',namespace='app01'))
url(r'^app02/',include('app02.urls',namespace='app02'))
print(reverse('app01:index')) print(reverse('app02:index'))
一般狀況下 起別名的時候 前面能夠加上你的應用名
建立一個app02:python manage.py startapp app02
總urls.py
from django.urls import path,re_path,include urlpatterns = [ path('app01/', include('app01.urls')), path('app02/', include('app02.urls')) ]
app01 的urls.py
from django.urls import path,re_path from app01 import views urlpatterns = [ re_path(r'index/',views.index,name='index'), ]
app02 的urls.py
from django.urls import path, re_path, include from app02 import views urlpatterns = [ re_path(r'index/', views.index,name='index'), ]
app01的視圖函數
def index(request): url=reverse('index') print(url) return HttpResponse('index app01')
app02的視圖函數
def index(request): url=reverse('index') print(url) return HttpResponse('index app02')
這樣都找index,app01和app02找到的都是app02的index
如何處理?在路由分發的時候指定名稱空間
總urls.py在路由分發時,指定名稱空間
path('app01/', include(('app01.urls','app01'))), path('app02/', include(('app02.urls','app02'))) url(r'app01/',include('app01.urls',namespace='app01')), url(r'app02/',include('app02.urls',namespace='app02')) url(r'app01/',include(('app01.urls','app01'))), url(r'app02/',include(('app02.urls','app02')))
在視圖函數反向解析的時候,指定是那個名稱空間下的
url=reverse('app02:index') print(url) url2=reverse('app01:index') print(url2)
在模版裏:
<a href="{% url 'app02:index'%}">哈哈</a>
一般針對不一樣的項目 只會安裝該項目所用的模塊 用不到的一律不裝
虛擬環境
不一樣的項目應該有各自獨立的解釋器環境 最大化節省資源
實際功能中針對不一樣的項目 會有一個叫requestsments.txt文件
該文件中列出來是一個個該項目須要用的到模塊名和版本號
eg:
django = 1.11.11
nginx = 1.21
後期經過命令直接會去下載該文件內全部的模塊及對應版本
不一樣的項目有專門的解釋器環境與之對應
每建立一個虛擬環境 就相似於從新下載了一個純淨的python解釋器
虛擬環境不要建立太多個
建議 你的機器上不要有態多的虛擬環境
當前咱們這個階段 建議你全部的模塊所有都安裝在本機環境中
虛擬環境的後期用法(瞭解)
python中經過requirements.txt來記錄項目全部的依賴包及其版本號,以便在其餘的環境中部署
(venv) $ pip freeze >requirements.txt
若是在開發的時候升級了依賴包,記得更新此文件!
在其餘環境部署項目以前先經過以下命令安裝依賴包,也就是當須要建立這個虛擬環境的徹底副本,能夠建立一個新的虛擬環境,並在其上運行如下命令:
(venv) $ pip install -r requirements.txt
pip的freeze命令保存了保存當前Python環境下全部類庫包,其它包括那些你沒有在當前項目中使用的類庫。 (若是你沒有的virtualenv)。
pip的freeze命令只保存與安裝在您的環境python全部軟件包。
但有時你只想將當前項目使用的類庫導出生成爲 requirements.txt;
使用方法:
$ pip install pipreqs $ pipreqs /path/to/project
django1.x
django2.x
區別1: urls.py中1.x用的是url,而2.x用的是path 而且2.x中的path第一個不支持正則表達式,寫什麼就匹配什麼 若是你以爲很差用,2.x裏面還有re_path 這個re_path就是你1.x裏面的url
django2.0的re_path和1.0的url同樣
思考狀況以下:
urlpatterns = [ re_path('articles/(?P<year>[0-9]{4})/', year_archive), re_path('article/(?P<article_id>[a-zA-Z0-9]+)/detail/', detail_view), re_path('articles/(?P<article_id>[a-zA-Z0-9]+)/edit/', edit_view), re_path('articles/(?P<article_id>[a-zA-Z0-9]+)/delete/', delete_view), ]
考慮下這樣的兩個問題:
第一個問題,函數 year_archive
中year參數是字符串類型的,所以須要先轉化爲整數類型的變量值,固然year=int(year)
不會有諸如如TypeError或者ValueError的異常。那麼有沒有一種方法,在url中,使得這一轉化步驟能夠由Django自動完成?
第二個問題,三個路由中article_id都是一樣的正則表達式,可是你須要寫三遍,當以後article_id規則改變後,須要同時修改三處代碼,那麼有沒有一種方法,只需修改一處便可?
在Django2.0中,可使用 path
解決以上的兩個問題。
這是一個簡單的例子:
from django.urls import path from . import views urlpatterns = [ 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>/', views.article_detail), # path才支持,re_path不支持 path('order/<int:year>',views.order), ]
基本規則:
<>
)從url中捕獲值。<int:name>
捕獲一個整數變量。若果沒有轉化器,將匹配任何字符串,固然也包括了 /
字符。如下是根據 2.0官方文檔 而整理的示例分析表:(跟上面url的匹配關係)
文檔原文是Path converters,暫且翻譯爲轉化器。
Django默認支持如下5個轉化器:
/
)以外的非空字符串,這是默認的形式對於一些複雜或者複用的須要,能夠定義本身的轉化器。轉化器是一個類或接口,它的要求有三點:
regex
類屬性,字符串類型to_python(self, value)
方法,value是由類屬性 regex
所匹配到的字符串,返回具體的Python變量值,以供Django傳遞到對應的視圖函數中。to_url(self, value)
方法,和 to_python
相反,value是一個具體的Python變量值,返回其字符串,一般用於url反向引用。例子:
class FourDigitYearConverter: regex = '[0-9]{4}' def to_python(self, value): return int(value) def to_url(self, value): return '%04d' % value
使用register_converter
將其註冊到URL配置中:
from django.urls import register_converter, path from . import converters, views register_converter(converters.FourDigitYearConverter, 'yyyy') urlpatterns = [ path('articles/2003/', views.special_case_2003), path('articles/<yyyy:year>/', views.year_archive), ... ]