模拟Django中的POST请求。

时间:2022-09-12 18:06:16

Let's suppose I have the following url: /valid/django/app/path/?foo=bar&spam=eggs

假设我有以下url: /有效/django/app/path/?foo=bar&spam=鸡蛋。

I can simulate a request to this URL in Django thusly:

我可以在Django中模拟对这个URL的请求:

from django.shortcuts import render
from django.core.urlresolvers import resolve

def simulate(request, url=None, template_name="not_important.html"):
    if url:
        dv = resolve(url.split('?')[0])
        return dv.func(request, *dv.args, **dv.kwargs)
    else:
        return render(request, template_name)

However, I'd like to include the parameters to the included view, so that the request.REQUEST and request.GET objects would also include foo and spam

但是,我希望将参数包含到包含的视图中,以便请求。请求,请求。获取对象还包括foo和spam。

I don't see how I can do this cleanly; as far as I understand the request.GET and request.REQUEST dictionaries are immutable so I can't merely do something like:

我看不出我能做得这么干净;就我所知的要求。获取和请求。请求字典是不可变的,所以我不能仅仅做一些类似的事情:

import urlparse

def simulate(request, url=None, template_name="not_important.html"):
    if url:
        dv = resolve(url.split('?')[0])
        qs = "".join(url.split('?')[1:])
        if qs:
            request.REQUEST.update(urlparse.parse_qs(qs))
            request.GET.update(urlparse.parse_qs(qs))
        return dv.func(request, *dv.args, **dv.kwargs)
    else:
        return render(request, template_name)

Or I'll get the error message

或者我会得到错误信息。

This QueryDict instance is immutable

这个QueryDict实例是不可变的。

for the request.GET object and

的请求。得到对象和

'MergeDict' object has no attribute 'update'

“MergeDict”对象没有属性“更新”

for the request.REQUEST object

的请求。请求对象

In case anyone is wondering why I want to do this: I want to allow users to fill out a form and then, when they submit, if they aren't logged in it sends them to a login form that includes the original URL in a hidden field. After logging in, rather than redirecting back to that link (which would be a GET request) I want it to call the original view, with the request variables it originally had, so that it can use the same POST request.

如果有人想知道我为什么要这样做:我想让用户填写表单,然后当他们提交时,如果他们没有登录,就会将他们发送到一个包含隐藏字段中原始URL的登录表单。在登录之后,而不是重定向回那个链接(这将是一个GET请求),我希望它调用原始视图,并使用它最初拥有的请求变量,以便它可以使用相同的POST请求。

And so of course in the process I'm also just interested in whether it would be possible to simulate a POST/GET request to a Django view when given a valid URL for the site.

当然,在这个过程中,我也很感兴趣的是,当给定一个有效的站点URL时,是否可以模拟POST/GET请求到Django视图。

2 个解决方案

#1


14  

request.GET/POST are QueryDict instances. According to the documentation on QueryDict, there are indeed "immutable" unless you clone them:

请求。GET / POST QueryDict实例。根据QueryDict的文档,确实存在“不可变”,除非您克隆它们:

QueryDict instances are immutable, unless you create a copy() of them. That means you can't change attributes of request.POST and request.GET directly.

QueryDict实例是不可变的,除非您创建它们的副本()。这意味着您不能更改请求的属性。邮报》和请求。直接得到。

You can copy, update and re-assign QueryDicts as such:

您可以复制、更新和重新分配QueryDicts:

ipdb> request.GET
<QueryDict: {u'x': [u'1']}>
ipdb> request.POST
<QueryDict: {}>
ipdb> request.REQUEST
MergeDict(<QueryDict: {}>, <QueryDict: {u'x': [u'1']}>)
ipdb> new_post = request.POST.copy()
ipdb> new_post.update(request.GET)
ipdb> request.POST = new_post
ipdb> request.POST
<QueryDict: {u'x': [u'1']}>
ipdb> request.GET
<QueryDict: {u'x': [u'1']}>
ipdb> request.REQUEST
MergeDict(<QueryDict: {}>, <QueryDict: {u'x': [u'1']}>)

The trick to update the MergeDict is to override its dicts attribute as such:

更新MergeDict的窍门是重写它的dicts属性:

ipdb> request.REQUEST
MergeDict(<QueryDict: {}>, <QueryDict: {u'x': [u'1']}>)
ipdb> request.REQUEST.dicts = (request.POST, request.GET)
ipdb> request.REQUEST
MergeDict(<QueryDict: {u'x': [u'1']}>, <QueryDict: {u'x': [u'1']}>)

Note that MergeDict is defined in module django.utils.datastructures, and instanciated in django.core.handlers.wsgi (and django.core.handlers.modpython) as such: self._request = datastructures.MergeDict(self.POST, self.GET).

注意,MergeDict是在模块django.utils中定义的。数据结构,并在django.core.handler中实例化。wsgi(和django.core.handlers.modpython): self。_request = datastructures.MergeDict(自我。帖子,self.GET)。

DISCLAMER: MergeDict is not documented, will break one day, and probably even kill some kittens. Use at your own discretion and with your own kittens. That said I like your use case, it's a pretty good idea.

DISCLAMER: MergeDict没有被记录,它会在某一天中断,甚至可能会杀死一些小猫。用你自己的谨慎和你自己的小猫。那就是说我喜欢你的用例,这是个好主意。

#2


0  

It is true than request.GET/POST are immutable objects, but you can actually MAKE them mutable (this is potentially dangerous) and change them directly, like this :

这是千真万确的。GET/POST是不可变的对象,但实际上可以使它们可变(这可能是危险的),并直接更改它们,如下所示:

request.GET._mutable = True

# make some changes, for example delete something inside
if 'var_name' in request.GET:
    del request.GET['var_name']

request.GET._mutable = False

#1


14  

request.GET/POST are QueryDict instances. According to the documentation on QueryDict, there are indeed "immutable" unless you clone them:

请求。GET / POST QueryDict实例。根据QueryDict的文档,确实存在“不可变”,除非您克隆它们:

QueryDict instances are immutable, unless you create a copy() of them. That means you can't change attributes of request.POST and request.GET directly.

QueryDict实例是不可变的,除非您创建它们的副本()。这意味着您不能更改请求的属性。邮报》和请求。直接得到。

You can copy, update and re-assign QueryDicts as such:

您可以复制、更新和重新分配QueryDicts:

ipdb> request.GET
<QueryDict: {u'x': [u'1']}>
ipdb> request.POST
<QueryDict: {}>
ipdb> request.REQUEST
MergeDict(<QueryDict: {}>, <QueryDict: {u'x': [u'1']}>)
ipdb> new_post = request.POST.copy()
ipdb> new_post.update(request.GET)
ipdb> request.POST = new_post
ipdb> request.POST
<QueryDict: {u'x': [u'1']}>
ipdb> request.GET
<QueryDict: {u'x': [u'1']}>
ipdb> request.REQUEST
MergeDict(<QueryDict: {}>, <QueryDict: {u'x': [u'1']}>)

The trick to update the MergeDict is to override its dicts attribute as such:

更新MergeDict的窍门是重写它的dicts属性:

ipdb> request.REQUEST
MergeDict(<QueryDict: {}>, <QueryDict: {u'x': [u'1']}>)
ipdb> request.REQUEST.dicts = (request.POST, request.GET)
ipdb> request.REQUEST
MergeDict(<QueryDict: {u'x': [u'1']}>, <QueryDict: {u'x': [u'1']}>)

Note that MergeDict is defined in module django.utils.datastructures, and instanciated in django.core.handlers.wsgi (and django.core.handlers.modpython) as such: self._request = datastructures.MergeDict(self.POST, self.GET).

注意,MergeDict是在模块django.utils中定义的。数据结构,并在django.core.handler中实例化。wsgi(和django.core.handlers.modpython): self。_request = datastructures.MergeDict(自我。帖子,self.GET)。

DISCLAMER: MergeDict is not documented, will break one day, and probably even kill some kittens. Use at your own discretion and with your own kittens. That said I like your use case, it's a pretty good idea.

DISCLAMER: MergeDict没有被记录,它会在某一天中断,甚至可能会杀死一些小猫。用你自己的谨慎和你自己的小猫。那就是说我喜欢你的用例,这是个好主意。

#2


0  

It is true than request.GET/POST are immutable objects, but you can actually MAKE them mutable (this is potentially dangerous) and change them directly, like this :

这是千真万确的。GET/POST是不可变的对象,但实际上可以使它们可变(这可能是危险的),并直接更改它们,如下所示:

request.GET._mutable = True

# make some changes, for example delete something inside
if 'var_name' in request.GET:
    del request.GET['var_name']

request.GET._mutable = False