django修改请求对象

时间:2013-09-21 07:48:57

标签: python django

我已经有了一个django项目,它的逻辑性如下:

url:URL?username = name& pwd = passwd

视图:

def func(request):
   dic = request.GET

   username = dic.get("username")
   pwd = dic.get("pwd")

但现在我们需要加密数据。然后,请求变为:

url:URL?crypt = XXXXXXXXXX(XXXXXXXX加密为“username = name& pwd = passwd”)

所以我需要修改每个视图功能。但是现在我想在django中间件中解密以防止修改每个视图函数。

但是当我修改request.GET时,我发现错误消息“这个QueryDict实例是不可变的”。我该如何修改它?

4 个答案:

答案 0 :(得分:78)

分配给request.GETrequest.POST

django.http.QueryDict个对象是不可变的。

您可以通过复制将其转换为可变QueryDict实例:

request.GET = request.GET.copy()

之后您将能够修改QueryDict

>>> from django.test.client import RequestFactory
>>> request = RequestFactory().get('/')
>>> request.GET
<QueryDict: {}>
>>> request.GET['foo'] = 'bar'
AttributeError: This QueryDict instance is immutable
>>> request.GET = request.GET.copy()
<QueryDict: {}>
>>> request.GET['foo'] = 'bar'
>>> request.GET
<QueryDict: {'foo': 'bar'}>

这是专门设计的,因此不允许任何应用程序组件编辑源请求数据,因此即使再次创建不可变QueryDict也会破坏此设计。我仍然建议您遵循指南并直接在中间件中的request对象上分配其他请求数据,尽管它可能会导致您编辑源。

答案 1 :(得分:37)

删除不变性:

if not request.GET._mutable:
   request.GET._mutable = True

# now you can spoil it
request.GET['pwd'] = 'iloveyou'

<强>更新

Django批准的方式是: request.GET.copy()

根据docs

  

在request.POST和request.GET中的QueryDicts在正常的请求/响应周期中访问时将是不可变的。要获得可变版本,您需要使用QueryDict.copy()。

没有什么能保证未来的Django版本将使用 _mutable 。这比 copy()方法有更多改变的机会。

答案 2 :(得分:5)

你不应该使用GET来发送用户名和密码,这是不好的做法(因为它显示了URL栏上的信息,可能会构成security risk)。相反,使用POST。此外,我猜你正在尝试对用户进行身份验证,而且您似乎正在做太多工作(创建一个新的中间件)来处理完全内置的内容,以便采取措施示例from the docs

from django.contrib.auth import authenticate, login

def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)
    if user is not None:
        if user.is_active:
            login(request, user)
            # Redirect to a success page.
        else:
            # Return a 'disabled account' error message
    else:
        # Return an 'invalid login' error message.

我自己真的很喜欢使用login_required decorator,非常简单易用。希望有所帮助

答案 3 :(得分:1)

request.GET._mutable = True

您需要这个。

def func(request):
   dic = request.GET
   request.GET._mutable = True #to make it editable 
   username = dic.get("username")
   request.GET.pop("pwd")
   request.GET._mutable = False #make it False once edit done