天天看點

Django中url的生成過程詳解

在前面我們知道,Django啟動之前會執行

admin.py

中的

autodiscover()

方法.

def autodiscover():
    autodiscover_modules('admin', register_to=site)           

在這個方法裡,既然

autodiscover_modules

能執行

admin.py

檔案,那當然也可以執行别的py檔案.

如果想讓

autodiscover_modules

執行自定義的py檔案,該怎麼做呢?

在app01的apps.py檔案的App01Config類中,定義ready方法

然後導入

autodiscover_modules

子產品,讓

autodiscover_modules

來執行自定義的py檔案

from django.apps import AppConfig
    
    class App01Config(AppConfig):
        name = 'app01'
    
        def ready(self):
            from django.utils.module_loading import autodiscover_modules
            
            autodiscover_modules("aaaa")           

這樣,程式在啟動的時候就會在項目所有的目錄下查找并調用

autodiscover_modules

方法來執行aaaa.py檔案

在app01目錄下建立aaaa.py檔案,在aaaa.py檔案中列印"hello world!"

可以看到在項目啟動之前就會在背景列印"hello world!"了.

Django中url的生成過程詳解

項目運作到這裡,下一步就是要生成URL了,這裡又是怎麼實作的呢???

建立一個text_url項目,包含appo1的應用,在項目的urls.py中配置url

urlpatterns = [
    url(r'^index/$',views.index),
]           

在app01的views.py中定義相應的視圖函數index

from django.shortcuts import render,HttpResponse
    
    def index(request):
        
        return HttpResponse("ok")           

以預設端口啟動項目,打開浏覽器輸入位址

http://127.0.0.1:8000/index/

Django中url的生成過程詳解

我們既然可以在views.py生定義視圖函數,當然也可以直接在urls.py中定義視圖函數index

from django.shortcuts import render,HttpResponse
    
    def index(request):
    
        return HttpResponse("aaaaaa")

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/$',index),
    ]           

重新開機項目,重新整理浏覽器,可以看到

Django中url的生成過程詳解

這樣也完成同樣的路由比對.

除了上面的兩種路由定義方法,我們還可以使用

include

方法來實作路由轉發功能.

from django.conf.urls import url,include
    
    urlpatterns = [
        url(r'^index/$',index),
        url(r'^app01/',include("url_test1"))
    ]
               

include

方法中,其參數表面是一個字元串,其實際是一個檔案路徑.

按照上面定義的方式,在app01這個應用目錄下建立url_test1檔案

url_test1檔案内容如下

from django.conf.urls import url,include
    
    urlpatterns = [
        url(r'^index/$',index),
    ]   
               

為什麼使用

include

方法也可以生成url,使用路由轉發的功能呢?

打開

include

方法,可以看到

def include(arg, namespace=None, app_name=None):
        ...         # 此處省略
    
        if isinstance(urlconf_module, six.string_types):
            urlconf_module = import_module(urlconf_module)
        patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
        app_name = getattr(urlconf_module, 'app_name', app_name)
        if namespace and not app_name:
            warnings.warn(
                'Specifying a namespace in django.conf.urls.include() without '
                'providing an app_name is deprecated. Set the app_name attribute '
                'in the included module, or pass a 2-tuple containing the list of '
                'patterns and app_name instead.',
                RemovedInDjango20Warning, stacklevel=2
            )
    
        namespace = namespace or app_name
            ...     # 此處省略
        
            return (urlconf_module, app_name, namespace)
               

`include方法執行完成以後,傳回的資料是一個元組類型.

既然

include

方法傳回的資料類型是元組類型,那麼在app01應用目錄下的url_test1.py中,也可以直接以元組的方式取代include方法.

from django.conf.urls import url
    from django.shortcuts import HttpResponse
    
    def index(request):
    
        return HttpResponse("bbbbbb")
    
    urlpatterns = [
        # url(r'^admin/', admin.site.urls),
        url(r'^index/$',index),
    ]           

重新開機項目,浏覽器位址更改為

http://127.0.0.1:8000/app01/index/

Django中url的生成過程詳解

include

方法中,傳回的元組有三個元素,第一個元素是

urlconf_module

include

方法中,有一個判斷方法

if isinstance(urlconf_module, six.string_types):
    urlconf_module = import_module(urlconf_module)
patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
app_name = getattr(urlconf_module, 'app_name', app_name)
               

由此可以知道如果

urlconf_module

是字元串類型,就以字元串方式導入了

urlconf_module

子產品.

導入子產品後,從子產品中擷取

urlpatterns

,如果沒有

urlpatterns

就使用預設值

urlconf_module

是以

include

方法傳回的資料第一個元素就是urls.py中

include

方法的參數.

而使用

include

方法進行路由分發時,被分發的路由中也會有

urlpatterns

是以進行路由分發時,urls.py檔案也可以寫成下面的樣子

urlpatterns = [
    url(r'^app01/',(url_test1,"test1","test2")),
]           

在app01目錄的url_test1檔案内容如下

from django.conf.urls import url
    from django.shortcuts import HttpResponse
    
    def index(request):
    
        return HttpResponse("cccccc")
    
    urlpatterns = [
        url(r'^index/$',index),
    ]           

重新開機項目,重新整理浏覽器

Django中url的生成過程詳解

在這裡url_test1做為元組的一個元素,其可以是子產品名,也可以是清單

可以用url_test1檔案中的urlpatterns替換urls.py檔案中的url_test1,這樣一來項目的urls.py内容就跟下面的代碼一樣了

from django.conf.urls import url,include
    from django.contrib import admin
    from app01 import views
    from app01 import url_test1
    from django.shortcuts import render,HttpResponse
    
    def index(request):
        return HttpResponse("aaaaaa")
    
    urlpatterns = [
        # url(r'^admin/', admin.site.urls),
        # url(r'^index/$',index),
        # url(r'^app01/',include("app01.url_test1")),
        url(r'^app01/',([
    
                    url(r'index/',index),
    
                        ],"test1","test2")),
    ]           
Django中url的生成過程詳解

可以看到,項目已經可以成功運作起來了

按照上面的步驟,一個項目的url可以再次進行分發

urlpatterns = [
        url(r'^app01/',([
    
                    url(r'index1/',([
                            url(r'index2/',index),
                    ],"test3","test4")),
    
                        ],"test1","test2")),
    ]           

重新開機項目,浏覽器打開

http://127.0.0.1:8000/app01/index1/index2/index

Django中url的生成過程詳解

現在有了index視圖函數,當然也可以有其他的視圖函數

urlpatterns = [
        url(r'^app01/',([
    
                    url(r'index1/',([
                            url(r'index2/',index),
                            url(r'index2/add',index),
                            url(r'index2/(\d+)/delete',index),
                            url(r'index2/(\d+)/change',index),
                    ],"test3","test4")),
    
                        ],"test1","test2")),
    ]           

這就是在Django背景進行資料表管理時使用的增删查改的urlr的生成方式

/userinfo/
/userinfo/add
/userinfo/(\d+)/delete
/userinfo/(\d+)/change           

再把上面urlpatterns中的url改變一下

urlpatterns = [
        url(r'^admin/',([
    
                    url(r'app01/',([
                            url(r'userinfo/',index),
                            url(r'userinfo/add',index),
                            url(r'userinfo/(\d+)/delete',index),
                            url(r'userinfo/(\d+)/change',index),
                    ],"test3","test4")),
    
                        ],"test1","test2")),
    ]           

把上面的url組合在一起,,就變成完完全全的Django背景進行資料表管理時使用的增删查改的url了.