1. 程式人生 > 其它 >CF1436E.Complicated Computations(線段樹)

CF1436E.Complicated Computations(線段樹)

django檢視

官方對於路由分發的介紹:
https://docs.djangoproject.com/zh-hans/3.2/topics/http/urls/

一般使用

路由分發應該在urls.py中進行。預設的根urls是通過settings檔案配置的:ROOT_URLCONF = '<專案名>.urls'
路由的分發靠的是urlpatterns列表來的定義的,其內的元素是pathre_path
如:

from django.contrib import admin
from django.urls import path

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

path的一般引數:path('admin/', admin.site.urls, name="myadmin")
admin/是一段字串,可以直接寫成url,也可以帶上過濾器,當django自上而下匹配到這個url時,會生成一個HttpRequest物件傳給檢視的的一個引數。
admin.site.urls是一個檢視函式,用於處理請求。
name="myadmin":name引數可以為dango的反向解析,動態生成url提供幫助,和app_name使用效果更好。

關於url以"/"結尾的匹配:如path('admin/', admin.site.urls)

可以匹配admin/admin,但若是path('admin', admin.site.urls)的話,就只能匹配到admin

路由轉發

通常,我們會在每個app裡,各自建立一個urls.py路由模組,然後從根路由出發,將app所屬的url請求,全部轉發到相應的urls.py模組中。
要實現這個功能,需要用到django.urls.include模組。

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path("app1/"
, include("app1.urls")), path("app2/", include("app2.urls")), ]

之後我們就可以在app的urls中做進一步的處理了。
需要注意的是:app.urls中接收到的url是已經去掉匹配部分的。如依照上面的路由,app1/user/index到了app1.urls中時,就剩下了user/index,所以寫路由分發時需要注意。而且app中的urls.py需要我們手動建立

轉換器

轉換器本質上就是一個使用正則表示式匹配url,但是它可以自動將url中匹配的內容轉換成我們需要的資料格式傳給request,也可以動態生成url。
預設情況下,Django內建下面的路徑轉換器:

  • str:匹配任何非空字串,但不含斜槓/,如果你沒有專門指定轉換器,預設使用該轉換器
  • int:匹配0和正整數,返回一個int型別
  • slug:可理解為註釋、字尾、附屬等概念,是url拖在最後的一部分解釋性字元。該轉換器匹配任何ASCII字元以及連線符和下劃線,比如building-your-1st-django-site;
  • uuid:匹配一個uuid格式的物件。為了防止衝突,規定必須使用破折號,所有字母必須小寫,例如075194d3-6885-417e-a8a8-6c931e272f00。返回一個UUID物件;
  • path:匹配任何非空字串,重點是可以包含路徑分隔符’/‘。這個轉換器可以幫助你匹配整個url而不是一段一段的url字串。要區分path轉換器和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:slug>/', views.article_detail),
]

'articles/<int:year>/'中的int是轉換器,而year是request中的引數名。

自定義轉換器

預設的轉換可以實現一般的匹配,但是假如要匹配複雜度和自定義程度比較高的url時,可以自定義一個轉換器。

第一步:自定義類
在app中建立一個converters.py,用於放置轉換器類

關鍵實現:

  1. 類屬性:regex
    這裡需要寫正則表示式
  2. 類方法:to_python
    轉換資料給檢視用,失敗要丟擲ValueError異常
  3. 類方法:to_url
    返回url供反轉操作,失敗要ValueError異常
# app/converters.py

class Year:
    regex = "\d{4}"

    def to_python(self, value):
        try:
            return int(value)
        except ValueError:
            raise ValueError

    def to_url(self, value):
        return value

第二步:在url中註冊

# polls/urls.py

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


app_name = "polls"		# app_name的作用後面講述
# 註冊轉換器為year_conv
register_converter(converters.Year, "year_conv")

urlpatterns = [
    path("", views.index, name="index"),
	# 和預設轉換器一樣使用自定義轉換器
    path("<year_conv:year>/", views.test, name="test"),
]

關於re_path

Django2.0的urlconf雖然改‘配置方式’了,但它依然向老版本相容。而這個相容的辦法,就是用re_path()方法。re_path()方法在骨子裡,根本就是以前的url()方法,只不過匯入的位置變了。下面是一個例子,對比一下Django1.11時代的語法,有什麼太大的差別?

from django.urls import path, re_path

from . import views

urlpatterns = [
    path('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),
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
]

path()方法的不同點:
捕獲URL中的引數使用的是正則捕獲,語法是 (?P<name>pattern) ,其中 name 是組名,pattern 是要匹配的模式。
傳遞給檢視的所有引數都是字串型別。而不像path()方法中可以指定轉換成某種型別。在檢視中接收引數時一定要小心。

反向解析及應用名稱空間

反向解析的功能可以動態生成url,防止我們將url寫死,減少維護複雜度。
反向解析可以在python程式碼中應用,也可以在django的template中應用。

如在urls中這樣定義:

from django.urls import path
from .views import index, article
urlpatterns = [
    path("index/", index, name="index"),
    path("article/<int:article_id>", article, name="article")
]
  • python程式碼中反向解析:

    # 1. 匯入django.urls.reverse函式
    # 2. 根據urls中path物件的name引數,確定你要生成的是那個url
    # 3. 假如url中需要引數的話,以args或kwargs傳入
    
    
    from django.http import HttpResponse
    from django.urls import reverse
    # Create your views here.
    
    
    def index(request):
    	index_url = reverse("index")
    	return HttpResponse(index_url)
    
    
    def article(request, article_id):
    	# article_url = reverse("article", args=(article_id, ))
    	article_url = reverse("article", kwargs={"article_id": article_id})
    	return HttpResponse(article_url)
    
  • 在template中反向解析:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Title</title>
    </head>
    <body>
    {% url "index" %}
    {% url "article" "1234" %}
    </body>
    </html>

    使用的是django模板引擎的url標籤,使用template時,應該要在settings中的INSTALLED_APPS新增上自己的app。

以上只利用path的name引數生成url的做法,在多個app時(如app1:name="index", app2:name="index")可能就不怎麼適用了。
因此django為我們提供了一個app_name變數,可以為我們標識不同的app。
在app/urls.py中我們可以自定義一個獨一無二的app_name,如:

from django.urls import path
from .views import index, article


app_name = "app01"

urlpatterns = [
    path("index/", index, name="index"),
    path("article/<int:article_id>", article, name="article")
]

在使用的時候只需要在name字元前面加上app_name:即可,如:

article_url = reverse("app01:article", kwargs={"article_id": article_id})

template的使用也是如此,改變第一個引數即可。

django還可以為不同的物件提供標識,實現方式時:給include新增name_space引數。具體可點選:關於includename_space的使用

我的github
我的部落格
我的筆記