我正在尝试使用中间件在Django rotue中捕获一个丢失的变量 - 但是我无法反转URL,因为Django无法找到视图(即使它存在于urlconf中)。例如:
通过这条路线:
# matches /test and /game/test
url(r'^((?P<game>[A-Za-z0-9]+)/)?test', 'hyp.views.test'),
我正在尝试检测是否未给出游戏部分,并在此情况下使用中间件重定向:
class GameMiddleware:
def process_view(self, request, view_func, view_args, view_kwargs):
if 'game' in view_kwargs:
game = view_kwargs['game']
if game is None:
# As a test, attempt to resolve the url
# Correctly finds ResolverMatch for hyp.views.test, game=TestGame
print resolve('/TestGame/test', urlconf=request.urlconf)
# Fails with "Reverse for 'hyp.views.test' with arguments '()'
# and keyword arguments '{'game': 'TestGame'}' not found."
return HttpResponseRedirect(reverse(
request.resolver_match.url_name, # 'hyp.views.test'
urlconf=request.urlconf,
kwargs={'game': 'TestGame'}
))
return None
request.urlconf
确实包含测试网址:
{ '__name__': 'urlconf', '__doc__': None, 'urlpatterns': [
<RegexURLPattern None ^$>,
<RegexURLPattern None ^((?P<game>[A-Za-z0-9]+)/)?test>
], '__package__': None }
我唯一能想到的是URL重写器可能无法处理包含可选部分的正则表达式 - 更好的解决方案是为这些情况创建单独的视图(我会有很多具有可选game
参数的视图)还是可以修复它?
我设法通过移除路线中的包裹括号来使其工作(因此它读取r'^(?P<game>[A-Za-z0-9]+/)?test'
并通过传递'TestGame /'作为游戏 - 但这不是理想的,因为我必须致电{每次{1}}(尽管只在中间件中)。使用game.rstrip('/')
标签也很难,因为预期以{% url %}
结尾的名称。
如果有人有更好的解决方案,请保持开放状态。
答案 0 :(得分:0)
感谢Todd's answer on another question,我找到了一个干净的方法:定义两条路线(一条游戏,另一条没有),在没有模式的路线中将游戏指定为None
:
url(r'^test$', 'hyp.views.test', {'game': None}),
url(r'^(?P<game>[A-Za-z0-9]+)/test', 'hyp.views.test'),
这会正确触发中间件的if game is None
部分,并且还允许指定游戏而不会使用斜杠。