如何将request.user转换为代理auth.User类?

cet*_*eek 17 django django-models

我有与此问题中提出的相同的难题,但适用于Django的auth.User.

我有这个代理模型:

class OrderedUser(User):
    def __unicode__(self):
        return self.get_full_name()

    class Meta: 
        proxy=True
        ordering=["first_name", "last_name"]
Run Code Online (Sandbox Code Playgroud)

我的一些其他模型使用的是字段类型OrderedUser而不是django.contrib.auth.models.User字段类型.

在我的视图中,我然后使用request.user填充字段和 - 正如预期 - 得到一个错误:

'Cannot assign "<User...>": <field> must be a "OrderedUser" instance'
Run Code Online (Sandbox Code Playgroud)

我可以做OrderedUser.objects.get(request.user.id),但这对数据库来说是一个额外的打击.

那么,如何将基础模型类转换为其代理类?

Dan*_*man 16

这是另一个数据库命中,但这将工作:

OrderedUser.objects.get(pk=request.user.pk)
Run Code Online (Sandbox Code Playgroud)

编辑您可以尝试:

o = OrderedUser()
o.__dict__ = request.user.__dict__
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的提示.我发现有一件事,当在context_processor中使用它来将用户对象传递给模板时......如果用户没有登录,你需要做不同的事情.正如你所拥有的,o总是以OrderedUser对象(来自User),但如果用户未登录,则应为AnonymousUser类型.所以我会测试`request.user.is_authenticated()`,如果是,那么只做以上操作.否则,请执行`o = request.user`. (3认同)
  • 是的,复制字典就可以了.谢谢Daniel. (2认同)

小智 14

我无法使用复制dict方法来处理Python 2.7.4和Django 1.6.我没有完全跟踪它,但我认为这与它是一个懒惰的对象有关.

什么对我有用:

request.user.__class__ = OrderedUser
Run Code Online (Sandbox Code Playgroud)

它避免了数据库调用,并允许访问基本身份验证和所有扩展行为.

为了使request.user始终像代理类一样,我在中间件之后将分配放在认证中间件之后,我的任何应用程序可以引用它之前.由于每次请求都会调用中间件,因此请确保在设置类之前对用户进行了身份验证.使用您的示例,以下是中间件代码的外观:

from yourapp.models import OrderedUser

class OrderedUserMiddleware():
    def process_request(self, request):
        if hasattr(request, 'user') and request.user.is_authenticated():
            request.user.__class__ = OrderedUser
Run Code Online (Sandbox Code Playgroud)

并记得在身份验证后注册中间件:

MIDDLEWARE_CLASSES = [
    # ...middleware from the guts of Django, none of your middle wares yet...
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # ...more middleware from the guts of Django, none of your middlewares yet...
    'yourapp.middleware.OrderedUserMiddleware',
    # ...more middleware from you other middlewares...
]
Run Code Online (Sandbox Code Playgroud)