在我的项目中,我有三个应用程序,"abc","xyz"和"common".Common并不是真正的应用程序,因为它只存储由两个应用程序继承和扩展的模板,模型和视图.
项目级urls.py看起来像这样,并正确地将请求重定向到相应的应用程序:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^abc/', include('abc.urls')),
url(r'^xyz/', include('xyz.urls')),
]
Run Code Online (Sandbox Code Playgroud)
两个应用程序的url.py文件都是这样的; 唯一的区别是用XYZ替换ABC的每个实例:
from django.conf.urls import url
from views import ABCAlertList as AlertList
from views import ABCEventList as EventList
from views import ABCEventDetail as EventDetail
from views import ABCEventReplay as EventReplay
from views import ABCUploadView as UploadView
urlpatterns = [
url(r'^$', AlertList.as_view(), name='view_alerts'),
url(r'^entities/(?P<uid>\w+)/$', EventList.as_view(), name='view_uid'),
url(r'^entities/(?P<uid>\w+)/replay/$', EventReplay.as_view(), name='view_replay'),
url(r'^entities/(?P<uid>\w+)/event/(?P<eid>\w+)/$', EventDetail.as_view(), name='view_event'),
url(r'^upload/$', UploadView.as_view(), name='upload_file'),
]
Run Code Online (Sandbox Code Playgroud)
同样,所有视图在两个应用程序之间都很常见,因此没有任何特定于应用程序的视图.两个应用程序在同一个通用模板中使用相同的行:
<a href="{% url 'view_uid' alert.uid %}">
Run Code Online (Sandbox Code Playgroud)
现在,问题是:
App ABC在顶级页面上运行正常.但它渲染的网址经过这一点指向错误的应用程序.
例如,我会进去的
http://localhost:8888/abc/
Run Code Online (Sandbox Code Playgroud)
并且该页面上的网址呈现为
http://localhost:8888/xyz/entities/262b3bce18e71c5459a41e1e6d52a946ab47e88f/
Run Code Online (Sandbox Code Playgroud)
是什么赋予了?看起来Django正在阅读错误的应用程序的urls.py.
Django无法区分视图名称和参数之下abc/和之间的URL xyz/.由于反转将以相反的顺序通过模式xyz/,因此下面的模式将始终匹配,因此使用reverse()或{% url %}标记生成的所有链接都将指向xyz应用程序.
您需要为每个模式指定唯一的名称,或使用URL命名空间.在Django 1.9+中你应该设置app_name属性:
app_name = 'abc'
urlpatterns = [
url(r'^$', AlertList.as_view(), name='view_alerts'),
url(r'^entities/(?P<uid>\w+)/$', EventList.as_view(), name='view_uid'),
url(r'^entities/(?P<uid>\w+)/replay/$', EventReplay.as_view(), name='view_replay'),
url(r'^entities/(?P<uid>\w+)/event/(?P<eid>\w+)/$', EventDetail.as_view(), name='view_event'),
url(r'^upload/$', UploadView.as_view(), name='upload_file'),
]
Run Code Online (Sandbox Code Playgroud)
在Django 1.8中,您需要将namespace参数传递给include():
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^abc/', include('abc.urls', namespace='abc')),
url(r'^xyz/', include('xyz.urls', namespace='xyz')),
]
Run Code Online (Sandbox Code Playgroud)
然后,您可以通过传递正确的命名空间来反转URL:
<a href="{% url 'abc:view_uid' alert.uid %}">
Run Code Online (Sandbox Code Playgroud)
如果您需要为两个应用程序使用相同的模板或函数,则需要将两个应用程序的应用程序命名空间设置为相同,但使用不同的实例命名空间.
在1.9+中,这意味着使用相同的app_name属性,但传递不同的namespace参数:
# myapp/urls.py
app_name = 'common_app_name'
urlpatterns = [
# app urls
]
# myproject/urls.py
urlpatterns = [
url(r'^abc/', include('abc.urls', namespace='abc')),
url(r'^xyz/', include('xyz.urls', namespace='xyz')),
]
Run Code Online (Sandbox Code Playgroud)
在模板中,您需要使用应用程序命名空间来反转URL.将自动考虑当前实例名称空间.在调用时reverse()需要传递当前命名空间:
reverse('common_app_name:view_alerts', current_app=request.resolver_match.namespace)
Run Code Online (Sandbox Code Playgroud)
在Django 1.8中你没有该app_name属性,你需要将它作为参数传递给include():
urlpatterns = [
url(r'^abc/', include('abc.urls', namespace='abc', app_name='common_app_name')),
url(r'^xyz/', include('xyz.urls', namespace='xyz', app_name='common_app_name')),
]
Run Code Online (Sandbox Code Playgroud)
Django 1.8也不会在调用{% url %}标记时自动使用当前实例名称空间.您需要为其设置request.current_app属性:
def my_view(request):
request.current_app = request.resolver_match.namespace
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
946 次 |
| 最近记录: |