django中app_name以及namespace理解

在写django的时候,html中反向解析经常会用到app_name 但有时候又是namespace,具体的区别如下:

  大部分情况 这两者有其一就可以了。 并且两者(可以简化理解)无区别

  只要一种情况   比如  访问   

    path(book1/, include(book.urls)),
    path(book2/, include(book.urls)),

       这种情况下(访问不通的url  但是执行的是一个app ,并且走一个方法或者类),必须用appname来区分,这时候用app_name就无法区分了!!

  以下测试实例来自  https://blog.51cto.com/jiajinh/2432449

 

 

  1. 在多个app之间,有可能产生同名的url,这个时候避免反转url的时候混淆,可以使用应用命名空间做区分。应用命名空间使用。在应用url中定义 app_name;

  2. 一个app,可以创建多个url映射到一个app中,所以就会产生一个问题,在做反转的时候,如果不使用命名空间,就会混淆,为了避免这个问题。我们可以使用实例命名空间。在include函数中添加namespace即可;

下面通过两个案例说明

一: 场景1,不同应用中的命名空间

(1)新建app应用

#python manage.py startapp app01
#python manage.py startapp app02

 

(2)主URL配置

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

urlpatterns = [
    path(admin/, admin.site.urls),
    path(app01/, include(app01.urls)),
    path(app02/, include(app02.urls)),
]

 

 

(2)app01配置 project_django/app01/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path(‘‘, views.index,name=index),
    path(login, views.login,name=login),
]

 

 

(3)app01配置 project_django/app01/views.py

from django.http import HttpResponse
from django.shortcuts import render
from django.shortcuts import redirect,reverse

# Create your views here.

def index(request):
    if request.GET.get("username"):
        return HttpResponse("front page app01!")
    else:
        return redirect(reverse("login"))

def login(request):
    return HttpResponse("Login page app01!")

 

(4)app02配置 project_django/app02/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path(‘‘, views.index,name=index),
    path(login, views.login,name=login),
]

 

 

(5)app02配置 project_django/app02/views.py

from django.http import HttpResponse
from django.shortcuts import render
from django.shortcuts import redirect, reverse

# Create your views here.

def index(request):
    if request.GET.get("username"):
        return HttpResponse("front page app02!")
    else:
        return redirect(reverse("login"))

def login(request):
    return HttpResponse("Login page app02!")

 

我们可以看到每个app下面的urls都定义了name=index和name=login。 而每个views下面的reverse都是login。这个时候django回去找谁呢? 当我们浏览器打开路径: http://127.0.0.1:8000/app01 的时候,我们会发现跳转异常,竟然跳转到地址: http://127.0.0.1:8000/app02/login 上面。

这个时候我们使用命名空间app_name,就可以很好解决这个问题。

修改配置

(1)app01配置 project_django/app01/urls.py

from django.urls import path
from . import views

#命名空间
app_name = app01   #这里变化了

urlpatterns = [
    path(‘‘, views.index,name=index),
    path(login, views.login,name=login),
]

 

 

(2)app01配置 project_django/app01/views.py

from django.http import HttpResponse
from django.shortcuts import render
from django.shortcuts import redirect,reverse

# Create your views here.

def index(request):
    if request.GET.get("username"):
        return HttpResponse("front page app01!")
    else:
        return redirect(reverse("app01:login"))   #这里变化了

def login(request):
    return HttpResponse("Login page app01!")

 

(3)app02配置 project_django/app02/urls.py

from django.urls import path
from . import views

app_name = app02   #这里变化了

urlpatterns = [
    path(‘‘, views.index,name=index),
    path(login, views.login,name=login),
]

 

 

(4)app02配置 project_django/app02/views.py

from django.http import HttpResponse
from django.shortcuts import render
from django.shortcuts import redirect, reverse

# Create your views here.

def index(request):
    if request.GET.get("username"):
        return HttpResponse("front page app02!")
    else:
        return redirect(reverse("app02:login"))  #这里变化了

def login(request):
    return HttpResponse("Login page app02!")

 

当我们浏览器打开路径: http://127.0.0.1:8000/app01 的时候,就会正常跳转地址: http://127.0.0.1:8000/app01/login 了

二: 场景2,同一个应用中的命名空间

先新启一个实例, #python manage.py startapp book

1. 我们先看一下代码案例,假设

(1)主URL,project_django/project_django/urls.py

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

urlpatterns = [
    path(admin/, admin.site.urls),
    path(book1/, include(book.urls)),
    path(book2/, include(book.urls)),
]
多个url,指向同一个app。

 

 

(2)应用book的子URL,project_django/book/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path(‘‘, views.book_list),
    path(login, views.book_login, name="login"),
]

 

(3)视图,project_django/book/views.py

from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
from django.shortcuts import redirect,reverse

def book_list(request):
    if request.GET.get("username"):
        return HttpResponse("My book list !!!!")
    else:
        return redirect(reverse("login"))

def book_login(request):
    return HttpResponse("Please Login!!!!")

 

 

通过上面案例,我们可以知道。
当执行http://127.0.0.1:8000/book2/ 的时候就会跳转http://127.0.0.1:8000/book2/login
当执行http://127.0.0.1:8000/book1/ 的时候发现还是跳转http://127.0.0.1:8000/book2/login

这不是我们想要的结果,我们希望访问/book1/的时候跳转/book1/login;访问/book2/的时候跳转/book2/login; 那么通一个应用中的两个实例,我们如何区分?

2. 案例修改

(1)主URL

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

urlpatterns = [
    path(admin/, admin.site.urls),
    path(book1/, include(book.urls),  namespace=book1)),  #变更部分
    path(book2/, include(book.urls),  namespace=book2)),  #变更部分
]

 

(2)应用book的子URL

from django.urls import path
from . import views

app_name = "book"

urlpatterns = [
    path(‘‘, views.book_list),
    path(login, views.book_login, name="login"),
]

 

(3)视图

def book_list(request):
        #获取当前namespace名称。
    current_namespace = request.resolver_match.namespace   #变更部分
    if request.GET.get("username"):
        return HttpResponse("My book list !!!!")
    else:
        print(current_namespace)
                #动态返回命名空间信息
        return redirect(reverse("%s:login"% current_namespace))  #变更部分

def book_login(request):
    return HttpResponse("Please Login!!!!")

 

 

三: include介绍

(1)include(module,namespace=Node)

  • module:应用app的名称.urls
  • namespace:实例命名空间。如果指定实例命名空间,那么必须指定应用命名空间。
    也就是在应用app的urls.py添加app_name=’xxx‘
    如果不加app_name,报错信息:‘Specifying a namespace in include() without providing an app_name ‘

(2)include((pattern_list,app_namesapace),namespace=None)

    • 如果不想在子app中的urls加app_name,那么就可以利用这种方法实现;
    • 例子:include((‘book.urls‘,‘book‘),namespace=‘book‘)

 

 

 

  

django中app_name以及namespace理解

上一篇:纯CSS模拟安卓滑动开关


下一篇:iOS滤镜和贴纸功能