簡體   English   中英

在Django中模擬POST請求

[英]Simulating a POST request in Django

我們假設我有以下網址: /valid/django/app/path/?foo=bar&spam=eggs

我可以在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)

但是,我想將參數包含在包含的視圖中,以便request.REQUEST和request.GET對象也包含foospam

我看不出我怎么能干凈利落地做到這一點; 據我所知,request.GET和request.REQUEST字典是不可變的,所以我不能只做以下事情:

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)

或者我會收到錯誤消息

此QueryDict實例是不可變的

對於request.GET對象和

'MergeDict'對象沒有屬性'update'

對於request.REQUEST對象

如果有人想知道我為什么要這樣做:我想允許用戶填寫表單然后,當他們提交時,如果他們沒有登錄,它會將它們發送到包含原始URL的登錄表單隱藏的領域。 登錄后,而不是重定向回到該鏈接(這將是一個GET請求),我希望它使用它最初具有的請求變量來調用原始視圖,以便它可以使用相同的POST請求。

當然,在這個過程中,我也只是感興趣的是,當給出該網站的有效URL時,是否可以模擬對Django視圖的POST / GET請求。

request.GET / POST是QueryDict實例。 根據QueryDict上的文檔, 除非你克隆它們,否則確實是“不可變的”:

QueryDict實例是不可變的,除非您創建它們的副本()。 這意味着您無法直接更改request.POST和request.GET的屬性。

您可以復制,更新和重新分配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']}>)

更新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']}>)

請注意, MergeDict在模塊django.utils.datastructures中定義,並在django.core.handlers.wsgi (和django.core.handlers.modpython)中實例化為: self._request = datastructures.MergeDict(self.POST, self.GET)

DISCLAMER :MergeDict沒有記錄,有一天會破壞,甚至可能會殺死一些小貓 您可以自行決定使用自己的小貓。 這就是說我喜歡你的用例,這是個不錯的主意。

它確實比request.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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM