Django:有什么方法可以避免在每个请求上查询 request.user ?
对于我的网站,几乎每个页面都有一个标题栏,显示“欢迎,ABC”,其中“ABC”是用户名。这意味着每个请求都会调用 request.user
,从而导致数据库一遍又一遍地命中。
但是一旦用户登录,我应该能够将他的 user
实例存储在他的 cookie 中并对其进行加密。这样我就可以避免重复访问数据库,而只需从 cookie 中检索 request.user
即可。
您将如何修改 Django 来做到这一点?有没有 Django 插件可以满足我的需要?
谢谢
For my website pretty much every page has a header bar displaying "Welcome, ABC" where "ABC" is the username. That means request.user
will be called for every single request resulting in database hits over and over again.
But once a user is logged in, I should be able to store his user
instance in his cookie and encrypt it. That way I can avoid hitting the database repeatedly and just retrieve request.user
from the cookie instead.
How would you modify Django to do this? Is there any Django plugins that does what I need?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您想要使用会话中间件,并且需要阅读文档< /a>.会话中间件支持多个会话引擎。理想情况下,您会使用 memcached 或 redis,但是 您可以编写您的自己的会话引擎将所有数据存储在用户的cookie中。启用中间件后,它就可以作为请求对象的一部分使用。您与
request.session
进行交互,它的作用类似于字典,使其易于使用。以下是文档中的几个示例:这个简单的视图在用户发表评论后将 has_commented 变量设置为 True。它不允许用户多次发表评论:
这个简单的视图登录网站的“成员”:
You want to use the session middleware, and you'll want to read the documentation. The session middleware supports multiple session engines. Ideally you'd use memcached or redis, but you could write your own session engine to store all the data in the user's cookie. Once you enable the middleware, it's available as part of the request object. You interact with
request.session
, which acts like a dict, making it easy to use. Here are a couple of examples from the docs:This simplistic view sets a has_commented variable to True after a user posts a comment. It doesn’t let a user post a comment more than once:
This simplistic view logs in a "member" of the site:
这有点过度优化的味道。从数据库获取用户是每个请求的一次点击,如果您也使用 Profile 模型,则可能是两次。如果您的网站额外的两个查询会对性能产生很大影响,那么您可能会遇到更大的问题。
This smells of over-optimisation. Getting a user from the db is a single hit per request, or possibly two if you use a Profile model as well. If your site is such that an extra two queries makes a big difference to performance, you may have bigger problems.
用户使用 django 提供的身份验证中间件(django.contrib.auth.middleware)附加到请求对象。它使用 django.contrib.auth.init 中的 get_user 函数从您正在使用的后端获取用户。您可以轻松更改此功能以在其他位置(例如 cookie)查找用户。
当用户登录时,django 将 userid 放入会话中(request.session[SESSION_KEY]=user.id)。当用户注销时,它会从会话中删除该用户的 ID。您可以覆盖这些登录和注销函数,以便将用户对象存储在浏览器的 cookie 中/从浏览器的 cookie 中删除用户对象。这两个函数也在 django.contrib.auth 中。init
请参阅此处设置 cookie:Django Cookie,我该如何设置它们?
The user is attached to the request object using the Authentication Middleware provided by django (django.contrib.auth.middleware). It users a function the get_user function in django.contrib.auth.init to get the user from the backend you are using. You can easily change this function to look for the user in another location (e.g. cookie).
When a user is logged in, django puts the userid in the session (request.session[SESSION_KEY]=user.id). When a user logs off, it erases the user's id from the session. You can override these login and logoff functions to also store a user object in the browsers cookie / erase user object from cookie in the browser. Both of these functions are also in django.contrib.auth.init
See here for settting cookies: Django Cookies, how can I set them?
一旦你有了适当的缓存,数据库命中的数量应该会显着减少——话又说回来,我并不是缓存方面的真正专家。我认为修改 request.user 来解决您的问题是一个坏主意。我认为更好的解决方案是创建一些实用程序、方法或自定义模板标签,尝试从 cookie 加载您所需的用户数据,并返回结果。如果cookie中没有找到用户数据,则应调用request.user,将数据保存到cookie中,然后返回结果。您可以使用 post_save 信号来检查用户数据的更改,以便您可以根据需要更新 cookie。
Once you have proper caching the number of database hits should be reduced significantly - then again I'm not really and expert on caching. I think it would be a bad idea to modify request.user to solve your problem. I think a better solution would be to create some utility, method or custom template tag that attempts to load your require user data from the cookie, and return the result. If the user data is not found in the cookie, then a call to request.user should be made, save the data to the cookie, and then return the result. You could possibly use a post_save signal to check for changes to the user data, so that you can make update to the cookie as required.