視圖通常都寫在app的views中,而且視圖的第一個參數永遠都是request(HttpRequest)對象。這個對象存儲了請求過來的全部信息,包括攜帶的參數以及一些頭部信息等。再視圖中,通常完成邏輯相關的操做,好比這個請求是添加一篇博客,那麼能夠經過request來接收到這些數據,而後存儲到數據庫中,最後再把執行的結果返回給瀏覽器。python
視圖函數的返回結果必須是HttpResponseBase對象或者HttpResponseBase子類的對象。正則表達式
django與flask傳遞參數區別:flask不須要傳遞這個request,是一個全局變量,django的request必須傳遞過來才能使用;數據庫
from django.http import HttpResponse def index(request): return HttpResponse(u"花花")
1.爲何回去urls.py文件中尋找映射呢?django
由於在settings.py中配置了ROOT_URLCONF爲urls.py:flask
ROOT_URLCONF = 'first.urls'
2.在urls.py中咱們全部的映射都應該放在urlpatterns這個變量中瀏覽器
urlpatterns = [ path('admin/', admin.site.urls), ]
3.全部的映射不是隨便寫的,而是經過path函數或者re_path函數進行包裝的。app
path = partial(_path, Pattern=RoutePattern)
re_path = partial(_path, Pattern=RegexPattern)
四、默認首頁映射查找模塊化
在沒有寫任何url映射時,django會給到一個默認的頁面,若是一旦有映射其餘url頁面,就要寫個視圖函數,url映射到空字符串,給到一個首頁;函數
urlpatterns = [ path('admin/', admin.site.urls), re_path(r'',views.index), ]
一、採用在url中使用變量的方式ui
在path的第一個參數中,使用<參數名>的方式能夠傳遞參數。而後在視圖函數中也要寫一個參數,視圖函數中的參數必須和url中的參數名稱保持一致,否則就找不到這個參數。另外,url中能夠傳遞多個參數
views.py
from django.http import HttpResponse def index(request): return HttpResponse(u"花花首頁") def book(request): return HttpResponse("圖書") def book_detail(request,book_id,category_id): text = "您獲取的圖書id是:%s,圖書分類是%s" % (book_id,category_id) return HttpResponse(text)
urls.py
from django.contrib import admin from django.urls import path,re_path from cmdb import views urlpatterns = [ path('admin/', admin.site.urls), path(r'',views.index), path(r'book/',views.book), path(r'book_detail/<book_id>/<category_id>/',views.book_detail), ]
結果:
二、採用查詢字符串的方式
在url中,不須要單獨的匹配查詢字符串的部分。只須要在視圖函數中使用request.GET.get('參數名稱')的方式來獲取。示例代碼以下:
path('book_author/',views.author_detail), def author_detail(request): author_id = request.GET['id'] #request包括客戶端和瀏覽器請求過來的全部數據 text = '做者的id是:%s' % author_id return HttpResponse(text)
訪問:http://127.0.0.1:8000/book_author/?id=2 便可將參數傳遞過去。
由於查詢字符串使用的是`GET`請求,因此咱們經過`request.GET`來獲取參數。而且由於`GET`是一個相似於字典的數據類型,全部獲取值跟字典的方式都是同樣的。
一、如何限制參數類型:
可使用django內置的url轉換器(converters)。咱們能夠從converters包中瞭解全部的轉換器,首先在urls.py中導入urls包引入轉換器,(快速打開converters.py方法:寫一行 "from django.urls import converters" 鼠標放在converters下ctrl+b)
from django.urls import converters
打開converters.py後能夠了解到全部的轉換器:
二、類型總結:
int類型:1個或者多個0-9的數字;
str類型:除了/
其他均可以做爲str類型,默認時str轉換器;
uuid類型:uuid轉換器具備惟一性,只知足uuid.uuid4()
類型的 ,如:923c3f5f-edeb-4d2b-ac70-a99eb4425b0b(print(uuid.uuid4()));
slug類型:數字、大小寫字母、-知足,其他不行;
path類型:str轉換器不能有/
而path轉換器是能夠包含任意字符的,包括/;
三、格式規範
只要在url,path中<參數名>前加格式類型便可
path(r'publisher_detail/<int:publisher_id>/',views.publisher_detail), #參數名前面加上格式類型 def publisher_detail(request,publisher_id): text = '出版社的id是:%s' % (publisher_id) return HttpResponse(text)
四、如何生成uuid?
進入python函數,uuid是python內置庫 >>> import uuid >>> print(uuid.uuid4()) 74858df0-7b95-4366-ae6c-dc54aa9402c6 #自動生成uuid >>>
當項目愈來愈大,url也會變得愈來愈多。若是放在主"urls.py"文件中,將會很差管理。所以咱們能夠將每一個app本身的urls放在本身的app中進行管理,通常咱們會在app中新建一個urls.py文件用來存儲全部和此app相關的url。
一、在app文件夾下新建一個urls.py文件,並寫入相關app的urls,注意要import 視圖函數
from django.urls import path from . import views urlpatterns = [ path(r'',views.book), path(r'detail/<book_id>/<category_id>/',views.book_detail), path('author/',views.book_author), path(r'publisher/<int:publisher_id>/',views.book_publisher), ##參數名前面加上格式類型 ]
二、在主urls.py中調入app的url
from django.urls import path,include #導入include模塊 path(r'',include('cmdb.urls')), #這邊我寫個空表明會找到urls表裏的第一個path映射的view path('book/',include('cmdb.urls')),
#url是會根據主 urls.py 和 app中的 urls.py 進行拼接,所以這邊book加了'/',app中的拼接前面就不須要加'/'了
三、須要注意的地方:
1) url模塊化是爲了方便管理,即將每一個APP中各創建本身的urls.py文件 。
2) 在項目下有一個總的urls.py文件,這個文件的主要做用是將每一個APP去找各自的urls.py文件,在該文件中,應該使用include函數包含urls.py,且是相對於項目路徑 。
3) 在APP中的urls.py文件,全部的匹配也應該放在urlpatterns中 。
4) 最終的url是根據主url.py和APP的url.py進行拼接的,所以,不可多加或少加/。
1.新建一個項目 在項目中建立cms和fomt兩個app。
2. 在cms應用的views.py文件裏輸入以下代碼:
from django.http import HttpResponse def index(request): return HttpResponse('CMS首頁') def login(request): return HttpResponse('CMSlogin登陸頁面')
3. 在fomt應用的views.py文件裏輸入以下代碼:
from django.http import HttpResponse def index(request): return HttpResponse('前臺首頁') def login(request): return HttpResponse('前臺登陸頁面')
4. 在cms和fomt兩個app裏各建立一個urls.py文件,分別寫下文件中代碼以下:
from django.urls import path from . import views urlpatterns = [ path('',views.index), path('login/',views.login), ]
5. 在項目的urls.py文件中更新代碼以下:
from django.urls import path,include urlpatterns = [ #path('admin/', admin.site.urls), path('',include('fomt.urls')), path('cms/',include('cms.urls')), ]
6. 實現url反轉
調整fomt應用views.py裏的代碼,實現未登錄用戶調轉到登錄頁面的功能。
調整後的代碼以下:
from django.shortcuts import render from django.http import HttpResponse from django.shortcuts import redirect #redirect重定向 def index(request): username = request.GET.get('username') #獲取查詢字符串 if username: return HttpResponse('前臺首頁') else: return redirect('/login/') #重定向到登陸頁面 def login(request): return HttpResponse('前臺登陸頁面')
訪問127.0.0.1:8000 直接跳轉到前臺登陸頁面
訪問http://127.0.0.1:8000/?username=huahua 跳轉到前臺首頁
7. url命名
爲何須要給url命名?
由於url是常常變化的。若是在代碼中寫死可能會常常改代碼。給url取個名字,之後使用url的時候就使用他的名字進行反轉就能夠了,就不須要寫死url了。
在fomt應用中views.py代碼修改以下:
from django.http import HttpResponse from django.shortcuts import redirect,reverse #redirect重定向 ,增長了reverse函數 def index(request): username = request.GET.get('username') #獲取查詢字符串 if username: return HttpResponse('前臺首頁') else: login_url=reverse('login') #urls.py中的url的name print(login_url)#在控制檯可查看打印的東西 return redirect(login_url) # 將login反轉的url賦值給login_url def login(request): return HttpResponse('前臺登陸頁面')
如何給url指定名稱?
在'path'函數中,傳遞一個'name'參數能夠指定。
在front應用中urls.py代碼修改以下:
from django.urls import path from . import views urlpatterns = [ path('',views.index,name='index'), path('signin/',views.login,name='login'), ] # 後期若是想將login改成signin,只須要將前面的「login/」修改成「signin/」便可,別的不用動。
訪問http://127.0.0.1:8000/自動跳到http://127.0.0.1:8000/signin/前臺登陸頁面;
在多個app之間,有可能產生同名的url。這時候爲了不反轉url的時候產生混淆,可使用應用命名空間,來作區分。定義應用命名空間很是簡單,只要在app的urls.py中定義一個叫作app_name的變量,來指定這個應用的命名空間便可。
’cms’的app應用views.py文件中給url命名:
from django.urls import path from . import views urlpatterns = [ path('',views.index,name = 'index'), path('login',views.login,name = 'login'), ]
訪問:http://127.0.0.1:8000/cms/login
發現跳轉至了cms登陸頁面去了,而咱們是想讓他跳轉至前臺登陸頁面啊!
這是由於咱們如今的項目中有兩個app,在這兩個app中咱們都將各自的主頁url取名爲‘index’,登陸頁面也都是命名爲’login’,在
return redirect( reverse('login') )
進行反轉的時候,Django不能準確的找到須要跳轉的頁面,因此他就會跳轉至找到的第一個’login’的頁面。這個時候咱們就須要讓Django明確的知道須要跳轉的頁面,因此咱們在每一個app中的urls.py中添加一個變量app_name
一、fomt中的urls.py中添加:
#應用命名空間 #應用命名空間的變量叫作app_name app_name = 'fomt'
二、在cms中的urls.py中添加:
app_name = 'cms'
三、而後咱們須要明確的指出須要跳轉的頁面,在front中的views.py中的index函數修
這樣之後左反轉的時候就可使用'應用命名空間:url名稱'的方式進行反轉;
def index(request): username = request.GET.get('username') if username: return HttpResponse('前臺首頁') else: login_url=reverse('fomt:login') #urls.py中的url的name return redirect(login_url)
訪問:http://127.0.0.1:8000 這樣Django就明確的知道須要跳轉至哪個頁面了。
一個app,能夠建立多個實例。便可以使用多個url映射同一個app。因此這就會產生一個問題。之後在作反轉的時候,若是使用應用命名空間,那麼就會發生混淆。爲了不這個問題。咱們可使用實例命名空間。實例命名空間也是很是簡單,只要在include函數中傳遞一個namespace變量便可。
1.在主urls.py中對cms添加兩個映射,而後實例化命名
from django.urls import path,include urlpatterns = [ #path('admin/', admin.site.urls), path('',include('fomt.urls')), path('cms1/',include('cms.urls',namespace='cms1')), path('cms2/',include('cms.urls',namespace='cms2')), ]
2.而後修改下cms的views.py中index函數的代碼,沒有傳入用戶名進來時直接跳轉至登陸頁面
from django.shortcuts import reverse,redirect def index(request): username = request.GET.get("username") if username: return HttpResponse('CMS首頁') else: # 獲取當前的命名空間 current_namespace = request.resolver_match.namespace return redirect(reverse("%s:login" % current_namespace))
們就使用cms1進入時,就會進入cms1的登陸頁面,使用cms2進入,就會進入cms2的登陸頁面,http://127.0.0.1:8000/cms2/login
一、include
(module,namespace = None):
module:子url的模塊字符串;
namespace:實例命名空間,若是指定實例命名空間,前提必需要先指定應用命名空間,也就是在子'urls.py'中添加'app_name'變量‘
二、include
(pattern_list):'pattern_list'是一個列表,這個列表中裝的是'path'或者're_path'函數;
三、include
((pattern_list,app_namespace),namespace = None): include函數的第一個參數既能夠爲一個字符,也能夠爲一個元祖,若是是元組,那麼元組的第一個參數是’urls.py‘
模塊的字符串,元組的第二個參數是應用命名空間,也就是說,應用命名空間既能夠在子'urls.py'中經過'app_name'指定,也能夠在'include'函數中指定;
一、re_path和path的做用都是同樣的。只不過re_path是在寫url的時候能夠用正則表達式,功能更增強大。
二、寫正則表達式都推薦使用原生字符串。也就是以r開頭的字符串。
三、在正則表達式中定義變量,須要使用圓括號括起來。這個參數是有名字的,那麼須要使用(?P<參數的名字>)。而後在後面添加正則表達式的規則。
四、編寫路由須要用的正則表達式,
r 字符串前面加「 r 」是爲了防止字符串中出現相似「\t」字符時被轉義。
^ 匹配字符串開頭;在多行模式中匹配每一行的開頭。 ^abc abc
$ 匹配字符串末尾;在多行模式中匹配每一行末尾
例如:
re_path(r"^list/(?P<year>\d{4})/$",views.article_list), re_path(r"^list/(?P<month>\d{2})/$",views.article_list_month)
第一個表示以list開始,中間須要有4個數字,一個都不能多也不能少,再以 ‘/’ 結尾。
形如list/2222/這樣的字符竄才能被識別,
同理,第二句是須要形如list/22/這樣的字符竄才能被識別。
例2:
from django.urls import path,re_path urlpatterns = [ re_path(r'^search_phone/$',views.search_phone), re_path(r'^sign_index/(?P<event_id>[0-9]+)/$', views.sign_index), re_path(r'^sign_index_action/(?P<event_id>[0-9]+)/$', views.sign_index_action),
若是不是特別要求。直接使用path就夠了,除非是url中確實是須要使用正則表達式來解決才使用re_path。
一、如若在反轉url時,須要添加參數,那麼能夠傳遞 kwargs 參數到 reverse 函數中,實例代碼以下:
views.py
from django.shortcuts import render,reverse,redirect from django.http import HttpResponse def index(request): username = request.GET.get('username') if username: return HttpResponse('首頁') else: detail_url = reverse('detail', kwargs={"article_id":'1'}) #使用 kwargs 參數到 reverse 函數中,也可添加多個參數; #detail_url = reverse('login') +"?next=/" return redirect(detail_url) def login (request): return HttpResponse('登陸頁面') def detail(request,article_id): text = '您的文章id是:%s' % article_id return HttpResponse(text)
urls.py
from django.urls import path from front import views urlpatterns = [ path('', views.index), path('login/', views.login), path('detail/<article_id>', views.detail,name='detail'), ]
二、如若想添加查詢字符串參數,則必須手動進行url拼接,
#detail_url = reverse('login') +"?next=/"
使用path或者re_path時,在route中均可以包含參數,而有時想指定默認參數,經過如下方式完成
url.py
path('', views.books), path('book/<int:page>/', views.books),
views.py
from django.http import HttpResponse book_list=[ '自動化', 'python', 'selenium' ] def books (request,page=0): return HttpResponse(book_list[page])
當訪問book的時候,由於沒有傳遞page參數,因此會匹配到第一個url,這時候view.books這個視圖函數,而在books函數中,又有page=0這個默認參數,所以這是就能夠不用傳遞參數,而若是訪問book/1的時候,由於在傳遞參數的時候傳遞了page,所以會匹配到第二個url,這時候也會執行views.books,而後把傳遞進來的參數傳給books函數中的page。