使用代理类,而不是用户的request.user
我有Django的User
模型元类,我用它来添加额外的方法(过于简化版本):使用代理类,而不是用户的request.user
# project.models.pie_lover.py
from django.contrib.auth.models import User
class PieLover(User):
class Meta:
app_label = "core"
proxy = True
def likes_pie(self):
return True
在我看来,我想得到登录PieLover
,看看他是否喜欢馅饼(因为PieLover
总是喜欢馅饼,所以很可笑,但在现实世界中情况可能并非如此)。我的问题在于Django登录用户的方式,我使用内置的login(request)
函数,因此存储在request.user
中的对象是User
对象,而不是PieLover
。
# project.views.like_pie.py
from ..models.pie_lover import PieLover
def index(request):
pie_lover = request.user
if pie_lover.likes_pie():
print "Try pie, try!"
else:
print "BLASPHEMER!"
如果我尝试这样做的Django告诉我,User
对象有没有方法likes_pie
这是可以预料的是request.user
不是PieLover
实例。
作为一种快速解决方法,我只需要获得与User
具有相同ID的PieLover
,但这意味着额外的数据库命中。
我该如何让Django默认在请求中使用PieLover
? 我在想,不是让另一个数据库查询得到正确的PieLover
对象来创建一个新的PieLover
对象,并在初始化时将request.user
传递给它,但我不知道这是什么意思。
打探后,我发现,是什么在我看来,要访问一个给定User
实例PieLover
方法最简单和非hackish的方式。我已经将此添加到自定义中间件:
from models.pie_lover import PieLover
class PieLoverMiddleware(object):
def process_request(self, request):
request.pie_lover = PieLover(request.user)
我该如何让Django在请求中默认使用PieLover?
你不知道。
阅读本你做任何事情之前:https://docs.djangoproject.com/en/1.3/topics/auth/#storing-additional-information-about-users
您的“分机”用户应该是所有的在单独的模型的扩展方法一个单独的模型。
然后,您可以使用已提供的get_profile()
方法,从用户(请求中)轻松导航至您的扩展。
S.Lott OP并没有谈论向模型中添加额外字段,只是几种方法。我认为最好的方法是单独处理lik @Ronnie或使用自定义的AuthenticationMiddleware – armonge 2012-01-12 23:10:51
@armonge:“并不是在向他的模型中添加额外的字段”。你确定?我的经验是,用户类的所有这些“增加”都涉及数据。这可能是罕见的例外。我仍然会建议内置的受支持的扩展机制总是最好的。 – 2012-01-12 23:13:19
@ S.Lott:不需要,只需要添加一些方法,我没有额外的数据。即使是这样的情况,当我可以轻松写入request.user.pie_lover.some_new_method() – yoshi 2012-01-13 00:04:55
from django.contrib.auth import models as auth_models
def _my_func(self):
return True
auth_models.User.my_func = _my_func
研究OSQA的扩展用户中间件。 – osa 2014-06-16 10:17:34