使用代理类,而不是用户的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) 
+0

研究OSQA的扩展用户中间件。 – osa 2014-06-16 10:17:34

我该如何让Django在请求中默认使用PieLover?

你不知道。

阅读本你做任何事情之前:https://docs.djangoproject.com/en/1.3/topics/auth/#storing-additional-information-about-users

您的“分机”用户应该是所有的在单独的模型的扩展方法一个单独的模型。

然后,您可以使用已提供的get_profile()方法,从用户(请求中)轻松导航至您的扩展。

+0

S.Lott OP并没有谈论向模型中添加额外字段,只是几种方法。我认为最好的方法是单独处理lik @Ronnie或使用自定义的AuthenticationMiddleware – armonge 2012-01-12 23:10:51

+0

@armonge:“并不是在向他的模型中添加额外的字段”。你确定?我的经验是,用户类的所有这些“增加”都涉及数据。这可能是罕见的例外。我仍然会建议内置的受支持的扩展机制总是最好的。 – 2012-01-12 23:13:19

+0

@ 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