如何在多部署的可重用Django应用中获取current_app以便与reverse一起使用?

8 投票
4 回答
7707 浏览
提问于 2025-04-15 17:48

我正在写一个可以重复使用的应用程序,并且想要多次部署它。

这是 urls.py 文件的内容:

urlpatterns = patterns('',
(r'^carphotos/', include('webui.photos.urls', app_name='car-photos') ),
(r'^userphotos/', include('webui.photos.urls',  app_name='profile-photos') ),)

还有 photos/urls.py 文件的内容:

urlpatterns = patterns('webui.photos.views',
url(r'^$', album_list, name="album-list" )
url(r'^newalbum/$', album_page, {'create': True}, name="album-create"),)

在 album_list 这个视图中,我想显示一个用于创建新相册 album_page 的链接。

我发现我需要使用 reverse 函数中的 current_app 参数来获取正确的 URL。

但是我该如何获取这个 current_app 呢?我以为答案会很简单,但在 Django 的文档中找不到。

谢谢,Nick

4 个回答

1

在你的网址中,虽然是同一个应用,但你用了不同的 app_name。把 app_name 设置成一样的,然后给每个实例设置一个独特的 namespace。比如:

urlpatterns = patterns('',
(r'^carphotos/', include('webui.photos.urls', app_name="webui_photos", namespace='car-photos') ),
(r'^userphotos/', include('webui.photos.urls', app_name="webui_photos", namespace='profile-photos') ),)

然后在使用反向解析的时候,提供 current_app 这个参数。可以查看一下 这个链接这个链接

[编辑] 重新看了一遍你的问题:

如果你使用 {% url %} 标签,就不需要提供 current_app 这个参数。根据我的理解,它会自动访问一个叫 current_app 的模板变量,这个变量会根据匹配的网址自动设置。

12

我知道这个问题已经很老了……但我觉得我找到了一个解决办法:

正如Will Hardy所建议的,你需要确保两个实例的app_name保持一致(或者根本不定义它,这样它会默认使用包含的URL所在的应用)。不过,每个应用实例要定义一个单独的命名空间:

urlpatterns = patterns('',
    (r'^carphotos/', include('webui.photos.urls', app_name="webui_photos", namespace='car-photos') ),
    (r'^userphotos/', include('webui.photos.urls', app_name="webui_photos", namespace='profile-photos') ),
)

接下来是设置当前活动应用实例(命名空间)在视图中的稍微复杂一点的部分。这意味着你需要找出哪个应用实例是活动的,并将其传递给RequestContext

要找出当前活动的应用,可以使用django.urls.resolve

r = resolve(request.path)
r.app_name  # the app name
r.namespace # the the currently active instance

所以你需要相应地更新你的视图(假设你使用的是基于类的视图):

from django.urls import resolve
from django.views.generic import TemplateView


class AlbumCreateView(TemplateView):
    template_name = 'path/to/my/template.html'
    
    def render_to_response(self, context, **response_kwargs):
        response_kwargs['current_app'] = resolve(self.request.path).namespace
        return super(AlbumPageView, self).render_to_response(context, **response_kwargs)

现在,url标签会自动反向到正确的命名空间,并且如果需要的话,仍然可以反向到特定的应用命名空间:

{% url webui_photos:album-create %} {# returns the url for whatever app is current #}
{% url car-photos:album-create %}
{% url profile-photos:album-create %}

在视图中反向生成URL时,必须手动传递当前的应用实例:

reverse('webui_photos:album-create', current_app=resolve(self.request.path).namespace))
-3

经过几天的研究,我发现把 Django 应用挂载多次并不太自然。

有一种可插拔应用的实现方式,具体可以参考这个链接:http://github.com/nowells/django-pluggables。不过对我来说,这看起来有点复杂。

所以我决定把重复的功能放到自定义标签里,并为我的应用每次使用都复制模板。我希望通过使用自定义标签和扩展功能,能帮助我遵循 DRY 原则(不要重复自己)。

撰写回答