1

我的 Django 应用程序中的每个用户都与一个部门相关联,几乎每个请求都涉及一些与部门相关的处理。所以我很想使部门对象在整个应用程序中都可用。

以下哪一项(如果有)是最合适的方法:

  1. 自定义中间件,它只是从数据库中检索相关部门并将其附加到request对象上,request.department比如 Django,AuthenticationMiddleware让当前登录的用户在request.user. (参见,例如,这里这里
  2. 当用户登录时将部门置于会话中,然后使用 Django 的request.session界面在视图中检索它。

我还没有机会熟悉 Django 的缓存功能,但我希望最终以每个用户为基础缓存该部门,以避免对每个请求造成额外的数据库命中。我看到Django 的会话提供了内置的缓存支持。我还想象缓存也可以用第一种方法来实现。

对于这种事情,使用会话(上面的#2)而不是自定义中间件(上面的#1)有优势吗?从内部 API 的角度来看,中间件方法似乎更干净,但我猜这正是会话的设计目的——所以也许这是开始使用它们的正确机会?

感谢您的任何指导!

4

1 回答 1

1

基本上这两种方法都非常相似。request.session方法可以消除手动在中间件中设置缓存的额外步骤。会话方法的坏处是,如果您使用开箱即用的缓存存储,则无法保证数据可用。例如,可能有 0.1% 的用户禁用了 cookie,您正在使用 memcache 存储,可能需要在重新部署时重新启动您的 memcache 服务器,并且您的登录用户将丢失他们的数据等。总而言之,我不会使用带有缓存存储的会话来存储关键数据。在我的项目中,我更喜欢使用第一个选项,因为它给了我更高级别的控制权。

您可以设置特殊的中间件,将view_name变量添加到请求并启用控制显示的位置和内容:

class NameMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):
        # add current view
        if isinstance(view_func, str):
            request.view_name = view_func
        elif hasattr(view_func, '__name__'):
            request.view_name = view_func.__name__

然后,您将更好地控制向请求提供附加信息的位置,例如在 context_processors 中,您可以仅将部门信息附加到选定的视图并以有效的方式缓存结果(如果需要,将请求代理到数据库):

def department_context_processor(request):
    if hasattr(request, 'view_name'):
        if request.view_name == 'department_view1' or request.view_name == 'department_view2':
            departments = cache.get('department_'+str(request.user), None)
            if departments is None:
                departments = Department.objects.filter(user=request.user)
                cache.set('department_'+str(request.user), departments, 60*60)
            if departments:
                return {
                    'departments': departments
                }
    return {}
于 2014-01-02T21:00:05.687 回答