django修改请求对象

use*_*567 59 python django

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

url:URL?username = name&pwd = passwd

视图:

def func(request):
   dic = request.GET

   username = dic.get("username")
   pwd = dic.get("pwd")
Run Code Online (Sandbox Code Playgroud)

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

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

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

但是当我修改request.GET时,我发现错误信息"这个QueryDict实例是不可变的".我怎么修改它?

Fil*_*vić 93

django.http.QueryDict分配给request.GETrequest.POST不可变的对象.

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

request.GET = request.GET.copy()
Run Code Online (Sandbox Code Playgroud)

之后你就可以修改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'}>
Run Code Online (Sandbox Code Playgroud)

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

  • 在Django 2.0中,当我尝试执行此操作时,出现AttributeError“无法设置属性” (8认同)

laf*_*ste 45

删除不变性:

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

# now you can spoil it
request.GET['pwd'] = 'iloveyou'
Run Code Online (Sandbox Code Playgroud)

更新

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

根据文件:

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

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

  • ...但更糟糕的是因为它修改了内部属性. (12认同)
  • 请不要建议这样做. (7认同)
  • 设置你的值之后你可以这样做:`request.GET._mutable = False`使它再次不可变. (6认同)
  • 这样可以更好地避免与POST请求上的copy()相关的成本 (4认同)

yuv*_*uvi 7

您不应该使用GET发送用户名和密码,这是一个不好的做法(因为它在URL栏上显示了信息,并且可能会带来安全风险)。而是使用POST。另外,我猜您正在尝试对用户进行身份验证,似乎您在做太多工作(创建新的中间件)来处理完全内置的内容,以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.
Run Code Online (Sandbox Code Playgroud)

我自己真的很喜欢使用login_required装饰器,使用起来非常简单。希望能有所帮助