Django - 路由層(URLconf)

1、django 靜態文件配置

/mysite1/settings.pycss

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static')
]

 

/templates/timer.htmlhtml

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>timer</title>
    <link rel="stylesheet" href="/static/timer.css">
</head>
<body>
<h4>當前時間:{{ date }}</h4>
</body>
<script src="/static/jquery-3.2.1.min.js"></script>
<script src="/static/timer.js"></script>
</html>

 

/static/...python

 

效果jquery

 

2、簡單得路由配置

URL配置(URLconf) 就像Django 所支撐網站的目錄。它的本質是URL與要爲該URL調用的視圖函數之間的映射表;你就是以這種方式告訴Django,對於客戶端發來的某個URL調用哪一段邏輯代碼對應執行。正則表達式

from django.urls import path,re_path

from app01 import views

urlpatterns = [
    re_path(r'^articles/2003/$',views.special_case_2003),
    re_path(r'^articles/([0-9]{4})/$',views.year_archive),  # year_archive(request,‘2009’)
    re_path(r'^articles/([0-9]{4})/([0-9]{2})/$',views.month_archive),
    re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$',views.article_detail),
]
from django.shortcuts import render,HttpResponse


def special_case_2003(request):

    return HttpResponse('special_case_2003')


def year_archive(request,y):

    return HttpResponse(y)


def month_archive(request,y,m):

    return HttpResponse(y+'-'+m)


def article_detail(request,y,m,d):

    return HttpResponse(y+'-'+m+'-'+d)

 

 

注意:django

  • 若要從URL 中捕獲一個值,只須要在它周圍放置一對圓括號。
  • 不須要添加一個前導的反斜槓,由於每一個URL 都有。例如,應該是^articles 而不是 ^/articles
  • 每一個正則表達式前面的'r' 是可選的可是建議加上。它告訴Python 這個字符串是「原始的」 —— 字符串中任何字符都不該該轉義

 示例:服務器

 一些請求的例子:

/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')。

3、有名分組

上面的示例使用簡單的、沒有命名的正則表達式組(經過圓括號)來捕獲URL 中的值並以位置 參數傳遞給視圖。在更高級的用法中,可使用命名的正則表達式組來捕獲URL 中的值並以關鍵字 參數傳遞給視圖。app

在Python 正則表達式中,命名正則表達式組的語法是(?P<name>pattern),其中name 是組的名稱,pattern 是要匹配的模式。函數

下面是以上URLconf 使用命名組的重寫:工具

from django.urls import path,re_path

from app01 import views

urlpatterns = [
    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),
    # views.month_archive(request, year='2005', month='03') 
]
from django.shortcuts import render,HttpResponse


def special_case_2003(request):

    return HttpResponse('special_case_2003')


def year_archive(request,year):

    return HttpResponse(year)


def month_archive(request,year,month):

    return HttpResponse(year+'-'+month)

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

/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')。

在實際應用中,這意味你的URLconf 會更加明晰且不容易產生參數順序問題的錯誤 —— 你能夠在你的視圖函數定義中從新安排參數的順序。固然,這些好處是以簡潔爲代價;

4、分發

from django.contrib import admin
from django.urls import path,re_path,include


urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/',include('blog.urls'))
] 
# blog.urls

from
django.contrib import admin from django.urls import path,re_path,include from blog import views urlpatterns = [ path('index/',views.index) ]
from django.shortcuts import render,HttpResponse

def index(request):

    return HttpResponse('OKok')

 

 

 

補充 

re_path(r'^$',views.index),

 

re_path(r'^',include('blog.urls')),

 

 

5、反向解析

在使用Django 項目時,一個常見的需求是得到URL 的最終形式,以用於嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用於處理服務器端的導航(重定向等)。人們強烈但願不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 絕不相關的專門的URL 生成機制,由於這樣容易致使必定程度上產生過時的URL。

在須要URL 的地方,對於不一樣層級,Django 提供不一樣的工具用於URL 反查:

  • 在模板中:使用url 模板標籤。
  • 在Python 代碼中:使用from django.urls import reverse()函數

 

在模板中

urls.py

from django.urls import path,re_path,include

from app01 import views

urlpatterns = [
    path('login.html/',views.login,name='Log'),

]

 

views.py

from django.shortcuts import render,HttpResponse

def login(request):
    if(request.method == 'POST'):
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')

        if(user == 'alice' and pwd == '123'):
            return HttpResponse('登陸成功')
        else:
            return HttpResponse('<h4 style="color:red;">登陸失敗</h4>')

    else:
        return render(request,'login.html')

 

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
{# url 控制器 action 默認 當前 反向解析 模板語法{{ }} 和{%  %} 兩種  #}
<form action="{% url 'Log' %}" method="post">
    用戶名:<input type="text" name="user">
    密碼:<input type="password" name="pwd">
    <input type="submit">
</form>
</body>
</html>

 

 

 補充:

 

在python中 

urls.py

from django.urls import path,re_path,include

from app01 import views

urlpatterns = [
    re_path(r'^articles/2003/$',views.special_case_2003,name='s_c_2003'),
    re_path(r'^articles/(?P<year>[0-9]{4})/$',views.year_archive,name='y'),
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})$',views.month_archive),
     
    path('index/',views.index,name='indexes')
]    

 

views.py

from django.shortcuts import render,HttpResponse

# 在python 裏面反向解析 不想寫死url 在之後會很靈活

from django.urls import reverse

def index(request):
    print(reverse('indexes'))
    # /app01/index/

    return HttpResponse('OKOK')


def special_case_2003(request):  # request 無論用不用,必定要寫
    url = reverse('s_c_2003')
    print(url)  # /app01/articles/2003/
    return HttpResponse('special_case_2003')


def year_archive(request,year):
    url = reverse('y',args=(year,))  # 這裏有這正則表達式
    print(url)  # /app01/articles/2018/
    return HttpResponse(year)


def month_archive(request,year,month):
    return HttpResponse(year+'-'+month)

 

注:當命名你的URL 模式時,請確保使用的名稱不會與其它應用中名稱衝突。若是你的URL 模式叫作comment,而另一個應用中也有一個一樣的名稱,當你在模板中使用這個名稱的時候不能保證將插入哪一個URL。在URL 名稱中加上一個前綴,好比應用的名稱,將減小衝突的可能。咱們建議使用myapp-comment 而不是comment

6、名稱空間

命名空間(英語:Namespace)是表示標識符的可見範圍。一個標識符可在多個命名空間中定義,它在不一樣命名空間中的含義是互不相干的。這樣,在一個新的命名空間中可定義任何標識符,它們不會與任何已有的標識符發生衝突,由於已有的定義都處於其它命名空間中。

因爲name沒有做用域,Django在反解URL時,會在項目全局順序搜索,當查找到第一個name指定URL時,當即返回
咱們在開發項目時,會常用name屬性反解出URL,當不當心在不一樣的app的urls中定義相同的name時,可能會致使URL反解錯誤,爲了不這種事情發生,引入了命名空間。
 
project的urls.py:
from django.urls import path,re_path,include

urlpatterns = [
    path('app01/',include(('app01.urls','app01'))), # 右面是名稱空間, 命名空間的意義
    path('app02/',include(('app02.urls','app02'))),

]

 

app01.urls:

from django.urls import path,re_path,include
from app01 import views

urlpatterns = [
    path('index/', views.index, name='index')

]

 

app02.urls:

from django.urls import path, re_path, include
from app02 import views

urlpatterns = [
    path('index/', views.index, name='index')
    
]   

 

app01.views 

from django.shortcuts import render,HttpResponse
from django.urls import reverse

def index(request):

    return HttpResponse(reverse('app01:index'))

 

app02.views

from django.shortcuts import render,HttpResponse
from django.urls import reverse

def index(request):

    return HttpResponse(reverse('app02:index'))

 

 

7、django2.0版的path

思考狀況以下: 

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 app01 import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<int:year>/', views.year_archive),  # year_archive(request,year)
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<slug:str_data>/', views.article_detail),
]
from django.shortcuts import render,HttpResponse


def special_case_2003(request):

    return HttpResponse('special_case_2003')


def year_archive(request,year):
    print(year,type(year))
    return HttpResponse(year)


def month_archive(request,year,month):
    print(year,type(year))
    print(month,type(month))
    return HttpResponse(month)


def article_detail(request,year,month,str_data):
    print(str_data,type(str_data))
    return HttpResponse(str_data)

 

基本規則:

  • 使用尖括號(<>)從url中捕獲值。
  • 捕獲值中能夠包含一個轉化器類型(converter type),好比使用 <int:name> 捕獲一個整數變量。若是沒有轉化器,將匹配任何字符串,固然也包括了 / 字符。
  • 無需添加前導斜槓。

 如下是根據 2.0官方文檔 而整理的示例分析表:

 

path轉化器

文檔原文是Path converters,暫且翻譯爲轉化器。

Django默認支持如下5個轉化器:

  • str,匹配除了路徑分隔符(/)以外的非空字符串,這是默認的形式
  • int,匹配正整數,包含0。
  • slug,匹配字母、數字以及橫槓、下劃線組成的字符串。
  • uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
  • path,匹配任何非空字符串,包含了路徑分隔符

 

註冊自定義轉化器

對於一些複雜或者複用的須要,能夠定義本身的轉化器。轉化器是一個類或接口,它的要求有三點:

  • regex 類屬性,字符串類型
  • to_python(self, value) 方法,value是由類屬性 regex 所匹配到的字符串,返回具體的Python變量值,以供Django傳遞到對應的視圖函數中。
  • to_url(self, value) 方法,和 to_python 相反,value是一個具體的Python變量值,返回其字符串,一般用於url反向引用。

 

urlconvert.py

'''
http://www.cnblogs.com/yuanchenqi/articles/8931472.html
https://docs.djangoproject.com/en/2.0/topics/http/urls/#example 
'''
# 自定義轉換器

class MonConvert:
    regex = '[0-9]{2}'

    def to_python(self,value):
        return int(value)

    def to_url(self,value):
        return '%04d'%value

 

urls.py  (使用register_converter 將其註冊到URL配置中)

from django.urls import path,register_converter
from app01 import views

from app01.urlconvert import MonConvert

# 註冊轉換器  註冊自定義的轉換器
register_converter(MonConvert,'mm')

urlpatterns = [
    # 本身註冊的轉換器
    path('articles/<mm:month>/', views.year_archive),
]

 

views.py

from django.shortcuts import render,HttpResponse

def year_archive(request,month):
    print(month,type(month))
    return HttpResponse(month)

 

 

 

總結:

django urls:
簡單配置
第一站: url 路徑匹配
有名分組
。。。 按關聯字傳參 (?P...) () 可傳參
分發:
多個app
反向解析
不想寫死url 別名name
名稱空間
防止名字起重了 配合反向解析使用
path # django 2.0 的特性
內部數值不會轉換 正則反覆使用

 含正則的 反向解析
https://www.cnblogs.com/yuanchenqi/articles/7629939.html

相關文章
相關標籤/搜索