2012-08-08 84 views
3

我在Apache上運行一個Django站點,它由Nginx實例作爲前端來服務我的靜態媒體。django-tastypie PATCH給我一個「400(Bad Request)」

我通過django-tastypie公開了一個API來模擬我需要修補的字段。當我做本地測試時(通過django runserver),一切都按預期工作。在現場服務器上,但是我收到「400(Bad Request)」。

我讀過幾個地方說Nginx不支持PATCH?是對的嗎?有沒有一個很好的解決方法?難道我做錯了什麼?

我只通過我想通過postData更新的字段發送。

jQuery代碼:

$.ajax({url: '...', 
    type: 'PATCH', 
    accepts: 'application/json', 
    contentType: 'application/json', 
    dataType: 'json', 
    data: postData, 
    processData: false, 
    success: function() { 
     // Success Code! 
    }, 
    error: function() { 
     // Error Code! 
    } 
}); 

Tastypie資源:

class ReceivedMessageResource(ModelResource): 
    """ 
    """ 
    campaign = fields.ForeignKey(CampaignResource, 'campaign') 
    campaign_name = fields.CharField(readonly=True) 
    campaign_id = fields.IntegerField(readonly=True) 
    message_type = fields.CharField(readonly=True) 
    display_date = fields.CharField(readonly=True) 
    attachments = fields.ToManyField('apps.campaign.api.AttachmentResource', 
            'attachment_set', 
            related_name='message', 
            full=True) 

    class Meta: 
     queryset = ReceivedMessage.objects.all() 
     resource_name = 'message' 
     filtering = {'id': ALL, 
        'campaign': ALL_WITH_RELATIONS} 
     excludes = ['reason', 'provider', 'loyalty_profile', 'original_message', 'date_received'] 
     allowed_methods = ['get', 'post', 'put', 'delete', 'patch'] 
     paginator_class = ReceivedMessagesPaginator 
     authentication = ApiKeyAuthentication() 
     authorization = DjangoAuthorization() 

如何解決這所有的方向可以理解的:)

+0

你想要修補的URL是什麼? api/v1/message /或api/v1/message/1 /? – santiagobasulto 2012-08-13 10:42:46

+0

我正在嘗試修補/ api/v1/message/1 /仍然沒有快樂。我看到這個[post](http://stackoverflow.com/questions/10069871/heroku-and-django-with-405-error),似乎表明我需要對Nginx做些事情,但對於我的生活,我不能找到那是什麼: -/ – 2012-08-13 16:49:16

+0

你應該開始嘗試去實現問題是什麼「層」。如果它在你的HTTP服務器上或你的應用程序中(Tastypie)。嘗試刪除身份驗證和授權,並進行一些測試。此外,將此添加到您的Meta類:detail_allowed_methods = ['patch'] – santiagobasulto 2012-08-13 17:21:29

回答

4

如果您使用的是最新版本的TastyPie的(從GitHub存儲庫中的一個,自8月5日),您可以按照指示from the documentation

使用PUT/DELETE/PATCH在不支持的地方

有些地方,比如在某些瀏覽器或主機,並不都通過PUT/DELETE/PATCH方法。在這些環境中,您可以通過提供一個X-HTTP-Method-Override標題來模擬這些類型的請求。例如,送過來POST一個PATCH請求時,你會像發送一個請求:

curl --dump-header - -H "Content-Type: application/json" -H "X-HTTP-Method-Override: PATCH" -X POST --data '{"title": "I Visited Grandma Today"}' http://localhost:8000/api/v1/entry/1/ 

所以,如果你的主機不支持此方法,添加X-HTTP-Method-Override頭與您正在嘗試的方法的名稱去表演。

+0

試一試,只是通過我的日誌,似乎X-HTTP-Method-Override標頭沒有從我的Nginx傳遞到我的Apache服務器。你知道我需要添加到我的Nginx conf中的proxy_pass設置嗎? – 2012-08-17 05:32:17

+0

我已經確認Apache實例(位於Nginx之後)沒有獲取X-HTTP-Method-Override標頭。我假設我需要以某種方式啓用我的Nginx將此標頭傳遞給Apache。 – 2012-08-17 05:44:02

+0

發現我的問題。我在JQuery中傳遞頭文件,例如'headers:{'X_HTTP_METHOD_OVERRIDE':'PATCH'},並且它應該是'headers':{'X-HTTP-Method-Override':'PATCH'}, – 2012-08-17 05:49:08

0

如果補丁沒有得到通過你的HTTP服務器,你可以僞造它。使用POST請求,並添加標題'X-HTTP-Method-Override':'PATCH'。 Tastypie的主分支在本文發佈時支持這一點。

如果您使用的是較早的版本,例如當前的穩定版本0.9.11,則可能需要一個小補丁。像this gist這樣的東西會教Tastypie使用該頭。

相關的部分是在這裏:

if request_method == 'post' and 'HTTP_X_HTTP_METHOD_OVERRIDE' in request.META: 
     request_method = request.META['HTTP_X_HTTP_METHOD_OVERRIDE'].lower() 
+1

這個想法很有趣,但並非必要:TastyPie已經以更靈活的方式支持「X-HTTP-Method-Override」頭文件。我已經發布了我的答案和相關信息。 – Tadeck 2012-08-16 10:49:59

+0

事實上,他們似乎已經在最新版本中增加了對此的支持。更新我的答案。 – dokkaebi 2012-08-17 01:49:29