Django URL中实例命名空间和应用程序命名空间有什么区别?

16
我正在参考https://www.webforefront.com/django/namedjangourls.html了解django urlconfs。我遇到了实例命名空间和应用程序命名空间这两个术语。我知道urlsconfs中的命名空间,但我不知道它们之间的区别。
我查阅了django文档,它提到当在django项目中使用同一应用程序的多个实例时,实例命名空间和应用程序命名空间就会出现。
但我仍然无法理解它。我已经在谷歌上搜过了,但没有找到任何帮助。
提前致谢。

不确定问题是什么,但Django在url conf中使用“namespace”参数来确定查找应该匹配视图函数名称的位置,即“'admin:index'”,其中admin是应用程序命名空间,因为admin是Django项目中的一个应用程序,而index是views.py模块中的一个视图函数。命名空间可以更改,默认情况下它使用带有“app_name”的应用程序模块,或者在Django2.0的情况下可以将其添加到url.py中,“app_name ='your_app_name'”。 - jackotonye
5个回答

30

将实例命名空间视为您的昵称,将应用程序命名空间视为您的真实姓名。

人们可以为您取很多昵称,但您的真实姓名不会改变。

Django使用应用程序命名空间(您的真实姓名)来反向生成URL,因为作为一个应用程序,您不需要关心有多少个实例命名空间(昵称)。

但为了区分一个实例和下一个实例,在urlconfs中将使用实例命名空间(昵称)。

假设您的应用程序涉及客户和商店员工。这两者都有物理地址,您可能希望使用一个只处理所有地址信息的应用程序:表单、验证、模型结构、地理位置等。我们虚构的应用程序是一个可重用的Django应用程序,名为 "django_super_address"。

您的根URL配置可能如下所示:

urlpatterns = [
    path('customer/address/',
         include('django_super_address.urls',
         namespace='customer_address')
    ),
    path('employee/address/',
         include('django_super_address.urls',
         namespace='employee_address')
    ),
]

这包括将相同的url放在不同的URL路径下,指向同一个应用,使用不同的命名空间(别名)。

django_super_address中,它定义了它自己的应用程序命名空间:

# File: django_super_address/urls.py
from . import views
app_name = 'django_super_address'

urlpatterns = [
    path('create/', views.SomeAddressCreateView.as_view(),
         name='address_create'),
    path('create/success/', views.SuccessView(),
         name='address_create_success'),
    ...
]

同时,在视图中,它使用:

# File django_super_address/views.py
class SomeAddressCreateView(generic.CreateView):
    def success_url(self):
        return reverse(
           'django_super_address:address_create_success'
        )
    ...

当Django获取URL "/employee/address/create/"时,它会执行以下操作:
  1. 将实例命名空间设置为"employee_address"
  2. 从 "django_super_address" 中读取 url
  3. 将应用程序命名空间设置为 "django_super_address" 并将 urls.py 与该应用程序命名空间关联。
在视图中:
  1. 通过查看与应用程序命名空间(真实名称)相关联的 urls 文件来反向解析 URL,然后将其命名为:"create/success"
  2. 然后,使用实例命名空间(昵称)将其余的URL前缀添加到URL中,即: "root" + "employee/address/" + "create/success/" = "/employee/address/create/success/"
这就是:URL配置文件的昵称和应用程序命名空间的反向解析。

3
我困惑的部分是为什么我会有两个指向同一应用程序的URL结构?这似乎是一个非常小众的用例。 - Eyad Arafat
1
如果我可以问一下,为什么“admin:index”是互联网上到处用来回答这个问题的示例呢?“index”不是视图名称而是实例命名空间吗? - Eyad Arafat
我正在尝试使用drf命名空间版本控制。 我在<app_name>/urls.py文件中缺少app_name。 有了这个解释,我能够理解并使用它。 - user
1
给出-1:如果您没有指定实例命名空间,而是在反向中使用应用程序命名空间,则将使用最后一个实例命名空间。如果您明确说明这一点,那么会更清晰。而不是只说“现在使用实例命名空间来添加前缀[...]”。这会引起“好的,但是反向如何知道要使用哪个实例命名空间...?”的困惑。 - Martín Nieva

6
根据我的理解,使用方法如下:
  • 当两个不同的应用程序使用相同的URL模式时,请使用应用程序命名空间
  • 当两个相同应用程序的不同实例使用相同的URL配置和视图时,请使用实例命名空间
实例命名空间的应用可能听起来有点混乱。 如果是这种情况,让我来尝试澄清一下。 请考虑Django文档中给出的示例。
 

urls.py:

from django.urls import include, path

urlpatterns = [
path('author-polls/', include('polls.urls', namespace='author-polls')),
path('publisher-polls/', include('polls.urls', namespace='publisher-polls')),
]

polls/urls.py:

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
...
]

命名空间的定义如下:
  • 应用程序命名空间polls/urls.py中的app_name属性定义
  • 实例命名空间urls.py中的namespace参数定义
在这里,author-pollspublisher-polls都使用相同的polls.urls来解析它们的URL。如果没有实例命名空间,解析类似'polls:index'的URL可能会让人困惑,不知道它要获取哪个URL。这就是为什么Django有一组协议,用于解决所有类型的情况,当您尝试反转和解析命名空间的URL时。

这是不正确的。特别是“对于使用相同URL模式的两个不同应用程序,请使用应用程序命名空间”。 - Melvyn Sopacua

1

命名空间实例只能与include一起使用。当我们想要有多个具有不同URL的路径,但是我们想要包含相同的URLconf模块时,这非常有用。

假设我们有以下代码:

#my_site/urls.py
urlpatterns = [
path('url1/',include('english.urls')),
path('url2/',include('english.urls'))]

#english/urls.py
app_name='english'
urlpatterns = [
path('words/', views.index, name='words')]

#template.html
<a href="{% url 'english:words' %}">Something</a>

点击链接将重定向到url1/words,因为Django将选择urlpatterns中的第一个元素。如果我们想要重定向到url2/words,我们必须使用命名空间(实例命名空间),即:
#my_site/urls.py
urlpatterns = [
path('url1/',include('english.urls', namespace='eng')),
path('url2/',include('english.urls', namespace='eng2'))]

#english/urls.py
app_name='english'
urlpatterns = [
path('words/', views.index, name='words')]

然后:

#template.html
<a href="{% url 'eng2:words' %}">Something</a>

我要补充一点,如果没有实例命名空间,Django 可能会发出警告:

警告:?(urls.W005) URL 命名空间 'english' 不是唯一的。您可能无法反向解析此命名空间中的所有 URL。

通常,在以下情况下实例命名空间很有用:

  • 我们希望根据用户的母语使用不同的 URL,例如:'django/documentation/'、'django/dokumentacja/' 或者 'django/en'、'django/pl'
  • 我们想要分离特定人群的 URL:'amazon/clients/'、'amazon/employees'
  • 我们已经更改了网站的 URL,并且为了不让旧用户感到困惑,我们还允许通过之前的链接访问网站。
  • 我们使网站在搜索引擎上易于被找到。

这不仅限于不同的 URL。即使我们使用相同的视图,我们也可以根据所在的 URL 稍微修改它们:

def index(request):
    current_url = request.path
    if current_url == '/url1/words/':
        ''' do something '''
    elif current_url == '/url2/words/': 
        ''' do something else '''
    return render(request, 'template.html')

我们可以例如更改上下文或选择不同的模板。

点击链接将重定向我们到url1/words,因为Django将选择urlpatterns中的第一个元素。Django会选择应用程序的最后出现的实例,即url2/words。我是对的吗? - S.B

0

基本上每个应用程序命名空间都可以有多个实例命名空间,例如:

这是项目URL文件(主URL):

path('', include("movie_app.urls")),
path('my_namespace1/', include("movie_app.urls", namespace='my_namespace1')),
path('my_namespace2/', include("movie_app.urls", namespace='my_namespace2')),

你可以看到,它们都提到了相同的app.urls文件(movie_app.urls),但路径链接是不同的。

第一个是:“”,

第二个是:“my_namespace1/”,

第三个是:“my_namespace2/”,

而这就是movie_app.urls文件(子文件):

app_name = 'movie_app'

urlpatterns = [
    path('appmovie1/', myview1 , name="myname"),   

]

现在当您在HTML模板中使用所有路径时,例如:

    <h1><a href="{% url 'movie_app:myname' %}"> application namespace : url name</a></h1>
    <h1><a href="{% url 'my_namespace1:myname' %}">instance namespace1 : url name</a></h1>
    <h1><a href="{% url 'my_namespace2:myname' %}">instance namespace2 : url name </a></h1>
  

你会注意到 href 链接中的差异:

    <h1><a href="/appmovie1/"> application namespace : url name</a></h1>
    <h1><a href="/my_namespace1/appmovie1/">instance namespace1 : url name</a></h1>
    <h1><a href="/my_namespace2/appmovie1/">instance namespace2 : url name </a></h1>
  

最后:
应用程序命名空间和实例命名空间将帮助您从使用相同的include .urls文件的多个URL路径中确定/选择正确的URL路径。
我希望这对您有所帮助。

0

您可以通过将urls.py包含在不同的URL路径中来为应用程序使用它,例如:

urlpatterns = [
    path('author-polls/', include('polls.urls')),
    path('publisher-polls/', include('polls.urls')), 
]

正如您所看到的,两个都包含了polls.urls:

app_name = 'polls' urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    ... 
]

目前为止还不错!

但是有一个问题。在模板中,'polls:index'指向哪里?!现在实例命名空间进入画面。

urlpatterns = [
    path('author-polls/', include('polls.urls', namespace='author-polls')),
    path('publisher-polls/', include('polls.urls', namespace='publisher-polls')), 
]

Django有一些规则来反转命名空间URL >> https://docs.djangoproject.com/en/3.0/topics/http/urls/#reversing-namespaced-urls


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接