带有动态前缀的Django URL

时间:2014-12-04 19:54:50

标签: python django

我需要为我的应用中的所有网址提供动态网址前缀。

我熟悉静态前缀,例如url(r'^myprefix/app', include('app.urls'))

相反,我需要myprefix是动态的,例如url(r'^(?P<prefix>\w+)/app', include('app.urls'))

这有效,但这里是踢球者。我不希望将prefix作为关键字参数发送到所有视图。我希望能够捕获它并在中间件或类似的东西中使用它。


为了给出我的具体用例,我们有用于管理各种测试实验室的软件(这个Django项目)。该应用程序需要了解它正在运行的实验室。

目前,我正在执行以下操作:

class LabMiddleware(object):
    def process_request(self, request):
        request.current_lab = 'lab1'  # Note that this is currently hard coded

该要求规定用户可以转到http://host/<lab_name>/app之类的网址,然后在我的LabMiddleware中使用lab_name。因此,我显然不希望在我的每一个观点中都接受lab_name,因为它很麻烦且过度。


更新

基于Sohan在答案中给出的内容,我最终使用了一个自定义中间件类:

urls.py

url(r'^(?P<lab_name>\w+)/', include('apps.urls')),

应用/ urls.py

url(r'^app1/', include('apps.app1.urls', namespace='app1')),

middleware.py

class LabMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):
        lab_name = view_kwargs.get('lab_name')
        if lab_name:
            request.current_lab = Lab.objects.get(name=lab_name)
            # Remove the lab name from the kwargs before calling the view
            view_kwargs.pop('lab_name')
            return view_func(request, *view_args, **view_kwargs)

settings.py

MIDDLEWARE_CLASSES = (
    # Default Django middleware classes here...
    'raamp.middleware.LabMiddleware',
)

这允许我在URL中包含实验室名称并将其添加到请求中。然后从view_kwargs中删除它,它不会被传递给视图函数,一切都按照我的意图运行。

另请注意,上面的代码并不是最优化的(例如,我为每个请求查询数据库)。我删除了用于缓存此代码的代码,因为显示此问题是如何解决并不重要,但值得一提的是,如果您在生产系统中使用它,则应对此代码进行一些改进。

1 个答案:

答案 0 :(得分:2)

您可以创建一个包装每个视图功能的装饰器。装饰者可以处理您在实验室名称参数上的任何处理工作,并且每个视图都不需要查看lab_name参数。

def process_lab_name(request, lab_name):
    request.current_lab = lab_name

def lab(view_func):
    def _decorator(request, lab_name, *args, **kwargs):
        # process the lab_name argument
        process_lab_name(request, lab_name)
        # when calling the view function, exclude the lab_name argument
        response = view_func(request, *args, **kwargs)
        return response
    return wraps(view_func)(_decorator)

@lab
def some_view(request):
    return render(...)

您的路线看起来像url(r'^(?P<lab_name>\w+)/app'