django中如何解析content-type=application/json的請求
本文由「大千AI助手」原創發布,專注用真話講AI,回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我,一起撕掉過度包裝,學習真實的AI技術!
往期文章回顧:
- 12.實測DeepSeek分詞機制:你的輸入如何變成計費Token? @2025-06-08 19:30:43+08:00
- 11.英語分詞進化論:BPE相關論文匯總 @2025-06-08 18:43:38+08:00
- 10.硬核實戰 | 3分鐘Docker部署ClickHouse列存數據庫 @2025-06-07 20:14:33+08:00
- 9.技術深解 | DeepSeek-R1-0528訓練參數全透視:163K上下文與MoE高效架構的基石 @2025-06-07 19:23:40+08:00
- 8.DeepSeek最新升級實測:推理能力翻倍,但離世界頂尖還有多遠? @2025-06-06 23:35:19+08:00
- 7.血淚教訓!Redis默認配置竟會導致數據丟失?Docker生產部署指南 @2025-06-06 00:00:00+08:00
- 6.Function Call:大模型如何突破自身局限“使用工具“ @2025-06-05 23:57:45+08:00
- 5.DeepSeek動手實踐:創建一個自動連點器 @2025-06-04 23:59:15+08:00
- 4.告別無效提示!使用少樣本學習讓AI秒懂你的需求 @2025-06-03 23:46:56+08:00
- 3.解密PromptTemplate:為什么說它是AI時代的Jinja模板? @2025-06-02 21:47:23+08:00
- 2.LangChain Core架構解析:模塊化設計與LCEL原語實現原理 @2025-06-01 21:02:36+08:00
- 1.拒絕重復造輪子!LangChain如何簡化LLM應用開發? @2025-06-01 07:42:09+08:00
問題描述
主要問題
Django原生開發時,View視圖里POST請求處理方法post
里通過request.POST
獲取content-type=application/json
類型的請求的請求體的結果為空字典{}
其他觀察
-
對于
content-type=application/x-www-form-urlencoded
類型的請求體能正常解析 -
對于
content-type=application/json
類型的請求,調試發現request.body
里包含請求的json字符串 -
處理視圖View的入參request的類型是
django.core.handlers.wsgi.WSGIRequest
原因分析
綜合分析上述問題和觀察結果,猜測django在解析請求的時候根據content-type
做了特殊區分處理
分析django源碼,發現request.POST
實際上是個property(POST = property(_get_post, _set_post)
)。
具體邏輯如下:
def _get_post(self):if not hasattr(self, '_post'):self._load_post_and_files()return self._postdef _set_post(self, post):self._post = post
而上述問題是查詢的時候無法獲取,因此繼續跟蹤_get_post
方法,_load_post_and_files
就是加載和解析post請求參數的主要邏輯,繼承自django.http.request.HttpRequest
。
具體邏輯如下
def _load_post_and_files(self):"""Populate self._post and self._files if the content-type is a form type"""if self.method != 'POST':self._post, self._files = QueryDict(encoding=self._encoding), MultiValueDict()returnif self._read_started and not hasattr(self, '_body'):self._mark_post_parse_error()returnif self.content_type == 'multipart/form-data':if hasattr(self, '_body'):# Use already read datadata = BytesIO(self._body)else:data = selftry:self._post, self._files = self.parse_file_upload(self.META, data)except MultiPartParserError:# An error occurred while parsing POST data. Since when# formatting the error the request handler might access# self.POST, set self._post and self._file to prevent# attempts to parse POST data again.# Mark that an error occurred. This allows self.__repr__ to# be explicit about it instead of simply representing an# empty POSTself._mark_post_parse_error()raiseelif self.content_type == 'application/x-www-form-urlencoded':self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict()else:self._post, self._files = QueryDict(encoding=self._encoding), MultiValueDict()
通過分析不難發現僅僅解析如下content-type
的請求體
multipart/form-data
- 也就是文件上傳application/x-www-form-urlencoded
- 其他類型 - 返回空字典(這也就解釋了為啥
content-type=application/json
時獲取的是個空字典)
解決方案
當抽絲剝繭找到問題的根本原因時,解決方案也就來了,那就是 自己解析 😂,當然你也可以投入djangorestframework
的懷抱,這是后話。
在構造form表單參數驗證前,根據request.content_type == 'application/json'
條件判斷,滿足的進行json字符串解析即可
方案示例
def post(self, request, *args, **kwargs):if request.content_type == 'application/json':# 這里可以增加一些異常處理邏輯body = json.loads(request.body)else:body = request.POST# 創建form表單form = CustomForm(body).... # 后續處理
One More Thing
授人以魚不如授人以漁,本文以Django中POST
請求處理時無法通過request.POST
直接獲取content-type=application/json
的請求體的問題為例,系統地展示在Django開發中遇到問題時,該如何從現象排查、問題定位、原因分析到最終解決的完整方法論。
本文由「大千AI助手」原創發布,專注用真話講AI,回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我,一起撕掉過度包裝,學習真實的AI技術!