1

我正在尝试使用中间件在 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 /'作为游戏传递 - 但这并不理想,因为我game.rstrip('/')每次都必须调用(尽管仅在中间件中) . 也很难使用标签作为以预期{% url %}结尾的名称。/

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

4

1 回答 1

0

感谢托德对另一个问题的回答,我找到了一种干净的方法:定义两条路线(一条有游戏,一条没有),将游戏指定为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部分,并且还允许指定游戏而不使用斜杠。

于 2013-04-13T22:45:40.840 回答