如何在Django模型中安全地访问请求对象 [英] How to safely access request object in Django models

查看:21
本文介绍了如何在Django模型中安全地访问请求对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要做的事情:

我正在尝试访问Django模型中的Request对象,以便可以使用request.user获取当前登录的用户。

我尝试的内容:

我在this站点上发现黑客攻击。但评论中有人指出,在生产时不要这样做。

我还尝试覆盖模型的__init__方法,就像thisPOST中提到的那样。但我收到AttributeError:'RelatedManager' object has no attribute 'request'

Models.py:

class TestManager(models.Manager):
    def user_test(self):
        return self.filter(user=self.request.user, viewed=False)

class Test(models.Model):

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super(Test, self).__init__(*args, **kwargs)

    user = models.ForeignKey(User, related_name='test') 
    viewed = models.BooleanField(default=False)
    objects = TestManager()

推荐答案

我尝试访问Django模型中的Request对象,以便可以使用request.user获取当前登录的用户。

嗯,问题是模型本身不是在请求上下文中使用的。例如,经常定义custom commands进行记账,或者可以定义一个API,例如用户不在的地方。Django方法的思想是模型应该而不是是请求感知的。模型定义业务逻辑层:模型定义实体及其交互方式。不尊重这些层会使应用程序容易受到很多问题的攻击。

您引用的博客旨在创建他们所说的全局状态(这是一个严重的anti-patten):当视图进行调用时,您将请求保存在中间件中,这样您就可以在模型层中获取该对象。这种方法有一些问题:首先,正如已经说过的,并不是所有的用例都是视图,因此并不是所有的用例都通过中间件。因此,该属性在获取时可能不存在

此外,不能保证请求对象确实是视图的请求对象。例如,我们可以将模型层与不通过中间件的命令一起使用,在这种情况下,我们应该使用先前的视图请求(因此可能使用不同的用户)。如果服务器同时处理多个请求,视图也可能看到几纳秒后到达的请求,因此再次使用错误的用户。身份验证中间件也可能是有条件的,因此并不是所有的请求都有user属性。简而言之,这样做可能失败的情况太多了,而且后果可能很严重:人们查看、编辑或删除他们不拥有的数据(没有查看、编辑或删除的权限)。

因此需要将requestuser对象传递给user_test方法。例如:

from django.http import HttpRequest

class TestManager(models.Manager):
    def user_test(self, request_or_user):
        if isinstance(request_or_user, HttpRequest):
            return self.filter(user=request_or_user.user, viewed=False)
        else:
            return self.filter(user=request_or_user, viewed=False)
因此,必须将request对象从视图传递到函数。即使这也不是真正的。真正的方法只接受user对象:

class TestManager(models.Manager):
    def user_test(self, user):
            return self.filter(user=user, viewed=False)

因此在视图中可以将其用作:

def some_view(request):
    some_tests = Test.objects.user_test(request.user)
    # ...
    # return Http response

例如,如果我们想用此查询集呈现一个模板,我们可以按如下方式传递它:

def some_view(request):
    some_tests = Test.objects.user_test(request.user)
    # ...
    return render(request, 'my_template.html', {'some_tests': some_tests})

这篇关于如何在Django模型中安全地访问请求对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆