对于我的网站,几乎每个页面都有一个标题栏显示“欢迎,ABC”,其中“ABC”是用户名。这意味着request.user
将为每个请求调用一次,从而导致数据库一次又一次地命中。
但是一旦用户登录,我应该能够将他的user
实例存储在他的 cookie 中并对其进行加密。这样我就可以避免重复访问数据库,而只是request.user
从 cookie 中检索。
你将如何修改 Django 来做到这一点?是否有任何 Django 插件可以满足我的需要?
谢谢
对于我的网站,几乎每个页面都有一个标题栏显示“欢迎,ABC”,其中“ABC”是用户名。这意味着request.user
将为每个请求调用一次,从而导致数据库一次又一次地命中。
但是一旦用户登录,我应该能够将他的user
实例存储在他的 cookie 中并对其进行加密。这样我就可以避免重复访问数据库,而只是request.user
从 cookie 中检索。
你将如何修改 Django 来做到这一点?是否有任何 Django 插件可以满足我的需要?
谢谢
这有过度优化的味道。从数据库中获取用户是每个请求的一次点击,如果您也使用 Profile 模型,则可能是两次。如果您的网站使得额外的两个查询对性能产生很大影响,那么您可能会遇到更大的问题。
您想使用会话中间件,并且需要阅读文档。会话中间件支持多个会话引擎。理想情况下,您会使用 memcached 或 redis,但您可以编写自己的会话引擎来将所有数据存储在用户的 cookie中。启用中间件后,它就可以作为请求对象的一部分使用。您与 进行交互request.session
,它的作用就像一个字典,使其易于使用。以下是文档中的几个示例:
这个简单的视图在用户发表评论后将 has_commented 变量设置为 True。它不允许用户多次发表评论:
def post_comment(request, new_comment):
if request.session.get('has_commented', False):
return HttpResponse("You've already commented.")
c = comments.Comment(comment=new_comment)
c.save()
request.session['has_commented'] = True
return HttpResponse('Thanks for your comment!')
这个简单的视图记录了站点的“成员”:
def login(request):
m = Member.objects.get(username=request.POST['username'])
if m.password == request.POST['password']:
request.session['member_id'] = m.id
return HttpResponse("You're logged in.")
else:
return HttpResponse("Your username and password didn't match.")
使用 django 提供的身份验证中间件(django.contrib.auth.middleware)将用户附加到请求对象。它使用 django.contrib.auth 中的 get_user 函数。init从您正在使用的后端获取用户。您可以轻松更改此功能以在其他位置(例如 cookie)查找用户。
当用户登录时,django 将用户 ID 放入会话中(request.session[SESSION_KEY]=user.id)。当用户注销时,它会从会话中删除用户的 ID。您可以覆盖这些登录和注销功能,以便在浏览器 cookie 中存储用户对象/从浏览器中的 cookie 中删除用户对象。这两个函数也在 django.contrib.auth 中。在里面
请参阅此处设置 cookie:Django Cookies,我如何设置它们?
一旦你有适当的缓存,数据库命中的数量应该会显着减少 - 然后我又不是真正的缓存专家。我认为修改 request.user 来解决您的问题是个坏主意。我认为更好的解决方案是创建一些实用程序、方法或自定义模板标签,尝试从 cookie 加载您需要的用户数据,并返回结果。如果 cookie 中没有找到用户数据,则应该调用 request.user,将数据保存到 cookie,然后返回结果。您可以使用 post_save 信号来检查用户数据的更改,以便您可以根据需要更新 cookie。