无法在中间件中反转视图

时间:2013-04-13 21:48:45

标签: django django-context

我正在尝试使用中间件在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 %}结尾的名称。

如果有人有更好的解决方案,请保持开放状态。

1 个答案:

答案 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部分,并且还允许指定游戏而不会使用斜杠。