Django i18n_patterns: resolve() 没有按预期工作
Django i18n_patterns: resolve() doesnt work as expected
解决这个问题后, there's another one: if you use the translation url system here https://docs.djangoproject.com/en/1.8/topics/i18n/translation/你会看到你添加了像urlpatterns += i18n_patterns(...)
这样的模式。
问题是基础 url 没有 语言没有被考虑,即:
resolve('/fr/produits/')
有效,
- 但
resolve('/produits/')
不起作用并引发 404。
如何解决?
这是我的 urls:
urlpatterns = [
url(r'^debug/?$', p_views.debug, name='debug'),
url(r'^i18n/', include('django.conf.urls.i18n')),
url(r'^login/(\w*)', p_views.login, name='login'),
url(r'^admin/', include(admin_site.urls)),
url(r'^public/(?P<path>.*)$',
'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT},
name='url_public'
),
]
urlpatterns += i18n_patterns(
url(_(r'^produits/detail/(?P<slug>[a-zA-Z0-9-_]+)/$'),
p_views.ProduitDetailView.as_view(), name='produits_detail'),
url(_(r'^produits/'),
p_views.IndexView.as_view(), name='produits_index'),
)
这是我制作的非常简单的 URL-tester(对应于 /debug
视图):
def debug(req):
def test(url):
try:
return u'<pre>{0} {1}</pre>'.format(url, resolve(url))
except Resolver404:
return u'<pre>{0} {1}</pre>'.format(url, 'None')
response = HttpResponse()
response.write(test('produits'))
response.write(test('produits/'))
response.write(test('/produits'))
response.write(test('/produits/'))
response.write(test('/fr/produits'))
response.write(test('/fr/produits/'))
response.write(test('/en/products/'))
response.write(test('/sv/produkter/'))
return response
这是 http://localhost:8000/debug
页面:
produits None
produits/ None
/produits None
/produits/ None
/fr/produits None
/fr/produits/ ResolverMatch(func=produits.views.IndexView, args=(), kwargs={}, url_name=produits_index, app_name=None, namespaces=[])
/en/products/ None
/sv/produkter/ None
最后三行应该都是 return ResolverMatch(...)
因为它们都是有效的 URLs.
Django 的 url 解析器仅适用于当前语言。
因此,在使用 translation.activate
.
尝试以特定语言解决 url 之前,您需要切换语言
对于解析 url,这意味着您必须事先了解该语言,切换到它然后才解析(基本上是 localemiddleware 将为您做的)。
为了反转 url,这意味着您可能应该使用其名称来反转 url。您将以当前语言取回 url。我现在无法测试,但它应该像这样工作:
from django.utils import translation
translation.activate('fr')
reverse('produits_index') # /fr/produits/
translation.activate('en')
reverse('produits_index') # /en/products/
如果您确实设法获得了一个 ResolverMatch
对象,则您将 url 名称作为其属性,方便地命名为 url_name
。
希望对您有所帮助,我不太清楚您要做什么。欢迎 comment/edit 你的问题,我会尝试更新这个答案。
Olivier Pons 更新
这是可行的解决方案:
这是我的工作解决方案,它接近于光谱,但按我想要的方式工作:
# (!) resolve() use current language
# -> try to guess language then activate BEFORE resolve()
lg_curr = translation.get_language()
lg_url = get_language_from_path(url) or lg_curr
translation.activate(lg_url)
try:
resolve(url)
req.session['url_back'] = url # no error -> ok, remember this
except Resolver404:
pass
translation.activate(lg_curr)
...然后,在成功 registration/login 之后,如果有 req.session['url_back']
然后我将其从会话中删除并对其进行重定向。
解决这个问题后urlpatterns += i18n_patterns(...)
这样的模式。
问题是基础 url 没有 语言没有被考虑,即:
resolve('/fr/produits/')
有效,- 但
resolve('/produits/')
不起作用并引发 404。
如何解决?
这是我的 urls:
urlpatterns = [
url(r'^debug/?$', p_views.debug, name='debug'),
url(r'^i18n/', include('django.conf.urls.i18n')),
url(r'^login/(\w*)', p_views.login, name='login'),
url(r'^admin/', include(admin_site.urls)),
url(r'^public/(?P<path>.*)$',
'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT},
name='url_public'
),
]
urlpatterns += i18n_patterns(
url(_(r'^produits/detail/(?P<slug>[a-zA-Z0-9-_]+)/$'),
p_views.ProduitDetailView.as_view(), name='produits_detail'),
url(_(r'^produits/'),
p_views.IndexView.as_view(), name='produits_index'),
)
这是我制作的非常简单的 URL-tester(对应于 /debug
视图):
def debug(req):
def test(url):
try:
return u'<pre>{0} {1}</pre>'.format(url, resolve(url))
except Resolver404:
return u'<pre>{0} {1}</pre>'.format(url, 'None')
response = HttpResponse()
response.write(test('produits'))
response.write(test('produits/'))
response.write(test('/produits'))
response.write(test('/produits/'))
response.write(test('/fr/produits'))
response.write(test('/fr/produits/'))
response.write(test('/en/products/'))
response.write(test('/sv/produkter/'))
return response
这是 http://localhost:8000/debug
页面:
produits None
produits/ None
/produits None
/produits/ None
/fr/produits None
/fr/produits/ ResolverMatch(func=produits.views.IndexView, args=(), kwargs={}, url_name=produits_index, app_name=None, namespaces=[])
/en/products/ None
/sv/produkter/ None
最后三行应该都是 return ResolverMatch(...)
因为它们都是有效的 URLs.
Django 的 url 解析器仅适用于当前语言。
因此,在使用 translation.activate
.
对于解析 url,这意味着您必须事先了解该语言,切换到它然后才解析(基本上是 localemiddleware 将为您做的)。
为了反转 url,这意味着您可能应该使用其名称来反转 url。您将以当前语言取回 url。我现在无法测试,但它应该像这样工作:
from django.utils import translation
translation.activate('fr')
reverse('produits_index') # /fr/produits/
translation.activate('en')
reverse('produits_index') # /en/products/
如果您确实设法获得了一个 ResolverMatch
对象,则您将 url 名称作为其属性,方便地命名为 url_name
。
希望对您有所帮助,我不太清楚您要做什么。欢迎 comment/edit 你的问题,我会尝试更新这个答案。
Olivier Pons 更新
这是可行的解决方案:
这是我的工作解决方案,它接近于光谱,但按我想要的方式工作:
# (!) resolve() use current language
# -> try to guess language then activate BEFORE resolve()
lg_curr = translation.get_language()
lg_url = get_language_from_path(url) or lg_curr
translation.activate(lg_url)
try:
resolve(url)
req.session['url_back'] = url # no error -> ok, remember this
except Resolver404:
pass
translation.activate(lg_curr)
...然后,在成功 registration/login 之后,如果有 req.session['url_back']
然后我将其从会话中删除并对其进行重定向。