2012-02-20 84 views
4

POST請求讓我們假設我有以下網址:/valid/django/app/path/?foo=bar&spam=eggs模擬在Django

我可以模擬這個網址在Django正是如此的要求:

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' 對象沒有屬性「更新」

爲request.REQUEST對象

如果你想知道我爲什麼要這麼做:我希望允許用戶填寫一個表格,然後,當他們提出,如果他們沒有登錄它將它們發送到包含隱藏字段中的原始URL的登錄表單。登錄後,而不是重定向回該鏈接(這將是一個GET請求),我希望它調用原始視圖,它與原來的請求變量,以便它可以使用相同的POST請求。

所以當然在這個過程中,我也只是感興趣的是,當給定站點的有效URL時,是否可以模擬向Django視圖發送POST/GET請求。

回答

14

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是覆蓋其類型的字典屬性爲這樣:

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未記錄,將歇一天,甚至可能殺死一些小貓。根據您自己的判斷和自己的小貓使用。這就是說我喜歡你的用例,這是一個不錯的主意。

+0

我認爲更新是在放置操作。您可能需要先分配副本,然後更新它 – jdi 2012-02-21 00:10:56

+0

絕對,謝謝jdi! FTR我實際上粘貼了一個測試POC :) – jpic 2012-02-21 00:13:00

+0

很高興你喜歡這個想法;在某些時候,我會嘗試提取它並在github上發佈它。如果我能弄明白,最終你所要做的就是用裝飾器包裝一個視圖,它會自動爲你處理。 – 2012-02-24 23:48:07

0

確實比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