我已经有了一个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实例是不可变的”。我该如何修改它?
答案 0 :(得分:78)
request.GET
和request.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