文章目錄
urls.py介紹
對於路由來說,urls.py至關重要,他負責告訴路由如何做,怎麼樣做,我們所有針對路由的操作基本都是在urls.py中完成的。官方有關urls的講解
官方也進行了一些簡單的實例(現在看不懂實例沒關係,下面我們會對路由詳細講解,相信你看懂下方的講解後,官方的實例對你來說就很容易看懂了)
功能視圖
1. 添加導入: from my_app import views
2. 給 urlpatterns 添加一個 URL: path('', views.home, name='home')
基於類的視圖
1. 添加導入: from other_app.views import Home
2. 給 urlpatterns 添加一個 URL: path('', Home.as_view(), name='home')
包括另一個 URLconf
1. 導入include()函數: from django.url import include,path
2. 給 urlpatterns 添加一個 URL: path('blog/', include('blog.urls'))
路由
最簡單的路由
我們創建最簡單的路由只需要引入兩個庫,分別是用來創建路由的path
與創建頁面相應的HttpResponse
即可。如下,最簡單的路由就創建完成了。我們再次打開頁面(默認爲127.0.0.1:8000)即可看到首頁已經被"我的首頁"所替代。
from django.urls import path
from django.http import HttpResponse
def home(request):
return HttpResponse("我的首頁")
urlpatterns = [
path('', home)
]
跨文件路由
上述事例中,我們的頁面就在路由中,但真實的情況下,我們不可能把所以頁面都寫在路由中,這裏我們可以將頁面寫在不同的APP中統一導入我們的路由。我們只需把需要路由的文件引入即可
# 當前APP的app_demo中的views.py中代碼爲
from django.shortcuts import render
from django.http import HttpResponse
# 在此處創建視圖。
def demo(request):
return HttpResponse('我是一個測試頁面')
我們可以把這個文件添加進入我們的路由
# 主項目的urls.py中的代碼爲
from django.urls import path
from app_demo.views import demo
urlpatterns = [
path('demo', demo)
]
或使用下列方式添加效果和上方完全相同
# 主項目的urls.py中的代碼爲
from django.urls import path
from app_demo import views
urlpatterns = [
path('demo/', views.demo)
]
APP中內置路由
如果存在大量APP可能會導致命名衝突,因爲每個APP中的視圖頁面默認都叫views.py,解決這個問題其實也很簡單,只需要我們內置APP路由即可。我們需要在APP中自行創建一個urls.py
並在內部寫入下列代碼,即可
from django.urls import path
from . import views
urlpatterns = [
path('', views.demo)
]
在主項目的路由中,我們需要使用urls庫中的include方法即可導入在APP中創建的urls
from django.urls import path, include
urlpatterns = [
path('demo/', include('app_demo.urls'))
]
傳參
URL中傳參也是非常重要的功能之一
簡單傳參
最簡單的傳參方式,我們只需要在視圖函數中傳入參數即可。
from django.urls import path
from django.http import HttpResponse
def home_page(request, home_id):
return HttpResponse("首頁的第"+home_id+'頁')
urlpatterns = [
path('<home_id>', home_page),
]
- 要從 URL 中取值,使用尖括號。
- 這裏不需要添加反斜槓,因爲每個 URL 都有。比如,應該是 demo 而不是 /demo。
路徑轉化器
默認情況下,我們可以接收任何形式的參數,但大多數時候,我們希望接收到的參數並不是任何形式都可以,比如說翻頁的時候我們想要接收到純數字的參數,或者我們想要接收純文本、uuid等。路徑轉化器就是爲此準備的。
假設我們現在想要接收一個純數字的id和一個由 ASCII 字母或數字以及連字符和下劃線組成的用戶名,我們可以寫成
from django.urls import path
from django.http import HttpResponse
def home_uid(request, home_id, home_name):
# <br>爲HTML的換行符
return HttpResponse('用戶的id:{}<br>用戶姓名:{}'.format(home_id, home_name))
urlpatterns = [
path('<int:home_id>/<slug:home_name>', home_uid),
]
路徑轉換器 | 作用 |
---|---|
str | 匹配除了 ‘/’ 之外的非空字符串。(默認選項) |
int | 匹配0或任何正整數。返回一個 int 。 |
slug | 匹配任意由 ASCII 字母或數字以及連字符和下劃線組成的短標籤。比如,building-your-1st-django-site 。 |
uuid | 匹配一個格式化的 UUID 。爲了防止多個 URL 映射到同一個頁面,必須包含破折號並且字符都爲小寫。 |
path | 匹配非空字段,包括路徑分隔符 ‘/’ 。它允許你匹配完整的 URL 路徑而不是像 str 那樣匹配 URL 的一部分。 |
除了內置的這五個路徑轉化器外,你還可以自定義路徑轉化器,自定義路徑轉化器方法
正則表達式識別參數(re_path)
除了使用路徑轉化器來接收指定形式的參數,我們還可以使用re_path來識別參數,使用他之前,我們需要先將其導入from django.urls import re_path
命名正則表達式組的語法是 (?P<name>pattern)
,其中 name 是組名,pattern 是要匹配的模式。注意:?P\<name>
這裏的必須寫,並且P必須爲大寫。
from django.urls import re_path
from django.http import HttpResponse
def home_year(request, year):
return HttpResponse('當前是{}年'.format(year))
urlpatterns = [
re_path('year/(?P<year>(1|2)[0-9]{3})', home_year),
]
常用傳參方式
我們在網站中見到的大部分傳參都已?
問號後方攜帶參數,Django實現這種傳參也相對容易,我們先假設一個需求,在app_demo這個APP中,我們需要多個以?
問號實現傳參翻頁的需求。
?
問號傳參的關鍵是request.GET.get('參數名')
傳參時,必須以指定的參數名傳入的參數才能接收到,否則無法接收,比如我在app_demo/views.py中寫入
from django.http import HttpResponse
def demo_page(request):
page = request.GET.get('data')
return HttpResponse('我第{}個測試頁面'.format(page))
URL中的就必須寫成http://127.0.0.1:8000/demo/page/?data=1
才能傳入參數
如果想自行上述代碼,需要在app_demo\urls.py中添加path('page/', views.demo_page)
,總路由中也要有path('demo/', include('app_demo.urls'))
指定默認參數
當一下特殊請求,直接進入指定網址後可能沒有攜帶參數,這時候我們可以使用指定參數讓頁面正確的跳轉到我們想要的地方
方法一: 我們可以直接在創建視圖函數時候給參數一個默認值,這裏需要注意的是,下方路由時需要給指定默認參數的頁面多一個默認的路由。
from django.urls import path, include
from django.http import HttpResponse
def home_uid(request, home_id=1, home_name='xunmi'):
return HttpResponse('用戶的id:{}<br>用戶姓名:{}'.format(home_id, home_name))
urlpatterns = [
path('home', home_uid),
path('home/<int:home_id>/<slug:home_name>', home_uid),
]
方法二: 使用request.GET.get('參數名')
方式接受參數的時候,我們會發現,如果沒有參數或接收失敗,會返回一個None,我們可以給一個if語句判斷返回值是否爲None即可。
def demo_page(request):
page = request.GET.get('data')
if page is None:
page = 1
return HttpResponse('我第{}個測試頁面'.format(page))
重定向
如果頁面中,我們接收到了錯誤的參數,如果不作爲,那麼頁面很可能會出現404等錯誤信息。爲了降低404的出現,我們可以做一些簡單的判斷,讓錯誤的id被重定向。這時候就需要用到redirect
這個方法,比如說下列代碼中就用到重定向將參數輸入錯的也頁面定向到上一層。
from django.shortcuts import render, redirect
from django.http import HttpResponse
# 在此處創建視圖。
def demo(request):
return HttpResponse('我是測試頁面')
def demo_page(request):
page = request.GET.get('data')
if page:
return HttpResponse('我第{}個測試頁面'.format(page))
else:
return redirect('../')
當前路由
from django.urls import path
from . import views
urlpatterns = [
path('', views.demo),
path('page/', views.demo_page)
]
URL 的反向解析
上述代碼中,我們的URL往往都是被寫死在代碼中的,要是出現一個在網站中多次被引用的的URL突然需要我們修改,這會是一個很麻煩的工作,並且可能會因爲漏改造成網頁錯誤跳轉引起bug。URL翻轉就是爲了解決此問題所誕生的,URL反轉也非常簡單,只需要在設置頁面路由的時候在path()
中添加name屬性,並在使用的的時候添加reverse
方法即可(在django.shortcuts
庫中,這個庫也是創建APP時攜帶的viwes.py中會帶的)
應用命名空間
在path中添加name即可比如path('home/', home_uid, name='index')
,在應用命名空間時,直接使用此命名即可,比如說反轉的時候調用,直接輸入reverse('index')
即可
from django.urls import path
from django.http import HttpResponse
from django.shortcuts import render, redirect, reverse
def home(request):
data = request.GET.get('id')
print(data)
if data:
return redirect(reverse('index'))
else:
return HttpResponse("我的首頁")
def home_uid(request, home_id=1, home_name='xunmi'):
return HttpResponse('用戶的id:{}<br>用戶姓名:{}'.format(home_id, home_name))
urlpatterns = [
path('', home),
path('home/', home_uid, name='index'),
path('home/<int:home_id>/<slug:home_name>', home_uid),
path('demo/', demo),
]
注: 應用命名空間與include
不能同時存在,比如path('demo/', include('app_demo.urls'), name='index')
此語句中的name就會失效。(如果上述情況我們想命名,可以去app_demo/urls.py
中添加name)
實例命名空間
我們在使用include時候爲了防止多個APP中出現了一樣的頁面造成命名衝突,還可以在自定義的urls.py中添加命名空間。我們可以在使用include的時候使用命名空間,不過命名空間用的最多的情況是反轉(反向解析)的時候,當我們反轉設置比較多的時候,可能就會造成衝突,且默認反轉是去APP本身的路由和項目總路由中尋找name,如果name存在在其他APP中,直接尋找就無法找到
# 在app_demo.py中添加
app_name = 'demo'
# 在使用include讀取路由的時候添加demo
path('demo/', include('app_demo.urls', 'demo')),
# 使用反轉(反向解析)添加命名空間
reverse('demo:index')
URL攜參反轉
可以直接在reverse()
反轉中添加kwargs
屬性即可比如return redirect(reverse('page', kwargs={'page': 1}))
如果需要使用帶?
問號的參數,可以用字符串拼接的方式,如下
from django.shortcuts import render, redirect, reverse
from django.http import HttpResponse
# Create your views here.
def copy(request):
# data = request.GET.get('id')
uid = request.GET.get('id')
if uid:
# 常規已反斜線形式傳參
# return redirect(reverse('page', kwargs={'page': data}))
# 已?形式傳參
data = reverse('copy:uid')+'?id='+uid
return redirect(data)
else:
return redirect(reverse('page', kwargs={'page': 1}))
def copy_page(request, page):
return HttpResponse('我是第{}頁'.format(page))
def copy_uid(request):
uid = request.GET.get('id')
return HttpResponse('我的id是{}'.format(uid))
此路由爲
from django.urls import path
from . import views
app_name = 'copy'
urlpatterns = [
path('', views.copy),
path('page/<page>', views.copy_page, name='page'),
path('uid/', views.copy_uid, name='uid')
]