Django_URL

視圖函數介紹

視圖通常都寫在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"花花")

URL映射

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中傳遞參數給視圖函數

一、採用在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轉換器

一、如何限制參數類型:

可使用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分層模塊化

 當項目愈來愈大,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進行拼接的,所以,不可多加或少加/。

URL命名與反轉URL

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)命名空間

在多個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函數用法

一、include(module,namespace = None)

module:子url的模塊字符串;

namespace:實例命名空間,若是指定實例命名空間,前提必需要先指定應用命名空間,也就是在子'urls.py'中添加'app_name'變量‘

二、includepattern_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和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。

reverse 函數補充

一、如若在反轉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。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息