自动生成 Django 嵌套 URL 命名空间 & reverse()

Autogenerating django nested URL namespaces & reverse()

我正在尝试根据 API 的模型数据自动生成一堆相似的 URL 和视图。我从模型中生成了一棵树并验证它是正确的。但是,当我尝试使用该树在嵌套命名空间中构建嵌套 URL 时,构建了 URL,但未构建命名空间。

相关代码:

# urls.py
urlpatterns = patterns('',
    url(r'^$', views.Index.as_view(), name='index'),
    url(r'^api/', include(rest_api.generate_urls('api'),
                          namespace='api', app_name='app')),
)

# rest_api.py
def build_urls(tree, namespaces):
    # Create the response function, which relies on data from tree
    if condition1:
        def response(request, **kwargs):
            ...
            return build_response(data_from_tree)
    elif condition2:
        def response(request, **kwargs):
            ...
            return build_response(data_from_tree)
    else:
        def response(request, **kwargs):
            ...
            return build_not_found_response(data_from_tree)
    urls = []
    # response will present unique identifier, URL for each entry in Model
    urls.append(url(r'^$', response, name='index'))
    # Add any sub-paths before open-ended regex.
    for path, node in tree.items():
        urls.append(url(r'^{path}/'.format(path=path),
                        include(build_urls(node, namespaces + (path,)),
                                namespace=path, app_name='app')))
    # response will query Model for appropriate entry & present data
    urls.append(url(r"^(?P<name>[\w ']+)", response))

    return patterns('', *urls)

def generate_urls(*namespaces):
    return build_urls(tree, namespaces)

当我查看生成的 URLconf(通过 django-extensions 中的 python manage.py show_urls)时,none 的嵌套名称空间在那里(已清理以便于阅读):

[riggs@dev app]$ python manage.py show_urls
/app/                              app.views.Index        index  
/app/api/                          app.rest_api.response  api:index   
/app/api/equipment/                app.rest_api.response  api:index   
/app/api/equipment/<name>          app.rest_api.response
/app/api/materials/                app.rest_api.response  api:index   
/app/api/materials/<name>          app.rest_api.response
/app/api/materials/raw/            app.rest_api.response  api:index   
/app/api/materials/raw/<name>      app.rest_api.response        
/app/api/materials/output1/        app.rest_api.response  api:index   
/app/api/materials/output1/<name>  app.rest_api.response        
/app/api/materials/output2/        app.rest_api.response  api:index   
/app/api/materials/output2/<name>  app.rest_api.response        
/app/api/recipe/                   app.rest_api.response  api:index   
/app/api/recipe/stage1/            app.rest_api.response  api:index   
/app/api/recipe/stage1/<name>      app.rest_api.response  
/app/api/recipe/stage2/            app.rest_api.response  api:index   
/app/api/recipe/stage2/<name>      app.rest_api.response        

我不明白为什么这不起作用。

等等,还有更多!

最终,我想要这些命名视图,以便我可以通过 django.core.urlresolvers.reverse 在 URL 中引用它们。尽管缺少嵌套,我还是能够通过更改

来测试 reverse
urls.append(url(r'^$', response, name='index'))

urls.append(url(r'^$', response, name=namespaces[-1]))

api:index 变成 api:equipmentapi:materialsapi:raw 等。但是,当我使用

测试这些名称时
def response(request, **kwargs):
    url = request.build_absolute_uri(
              reverse(':'.join(('api', viewname)),
                      current_app=request.resolver_match.namespace))
    ...
    return build_response(data_from_tree)

Django 抛出 NoReverseMatch 消息 Reverse for 'equipment' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []

我做错了什么? django 真的能做我想做的吗?

结果证明上面的效果很好! show_urls 不处理名称空间,因此我假设名称空间是错误的,因此掩盖了一个不同的错误。一旦我相信它们是正确的,我就能够找到有问题的代码。