2017-05-22 110 views
1

我有Django的1.10項目及以下用戶定義的中間件編輯響應contect

class RequestLogMiddleWare(object): 
    def __init__(self, get_response): 
     self.get_response = get_response 

    def __call__(self, request): 
     response = self.get_response(request) 
     response.data['detail'] = 'I have been edited' 
     return response 

和REST的端點觀點:

def r_mobile_call_log(request): 
    return Response({'success': True, 
        'detail': 'Before having been edited'}, 
         status=status.HTTP_200_OK) 

,所以我期望的最終響應客戶端是:

{'success': 'True', 'detail': 'I have been edited'} 

不過,我看到的是:

{'success': 'True', 'detail': 'Before having been edited'} 

我在中間件的調用方法中放置了一個斷點,以確保該函數真正執行,並且沒關係。 response.data["details"]只是不會改變它的價值。任何人都知道這是什麼原因? 預先感謝您

回答

3

Response已經呈現在中間件階段,因此您不能只更改response.data,您需要重新渲染它或直接更改呈現的內容。

class RequestLogMiddleWare(object): 
    def __init__(self, get_response): 
     self.get_response = get_response 

    def __call__(self, request): 
     response = self.get_response(request) 
     if isinstance(response, Response): 
      response.data['detail'] = 'I have been edited' 
      # you need to change private attribute `_is_render` 
      # to call render second time 
      response._is_rendered = False 
      response.render() 
     return response 

第二種方法只是改變的內容直接,但在這種情況下,建於REST框架的瀏覽器的API將無法工作,因爲模板無法正常顯示。

import json 

class RequestLogMiddleWare(object): 
    def __init__(self, get_response): 
     self.get_response = get_response 

    def __call__(self, request): 
     response = self.get_response(request) 
     if isinstance(response, Response): 
      response.data['detail'] = 'I have been edited' 
      response.content = json.dumps(response.data) 
     return response 

source code for render method

0

我有一種感覺,我發現了清晰的解決方案。以下是我重寫代碼的方式:

class RequestLogMiddleWare(object): 
def __init__(self, get_response): 
    self.get_response = get_response 
    def __call__(self, request): 
     response = self.get_response(request) 

    def process_template_response(self, request, response): 
     if hasattr(response, 'data'): 
      response.data['detail'] = 'bla-bla-bla' 
     return response