You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python发送x-www-form-urlencoded格式的PATCH请求?

问题描述

向Zulip接口发送PATCH请求编辑草稿时,返回Missing 'draft' argument错误。现有代码如下:

draft_content = body_serializer.data['content']
recipient_stream_id = user_to.zulip_id
topic = "draft"
draft_type = "private"

data = {"draft" : {
    "content": draft_content,
    "to": [recipient_stream_id],
    "topic": topic,
    "type": draft_type
}}

try:
    response = requests.patch(
        f'{settings.ZULIP_SITE}api/v1/drafts/{draft_id}',
        headers={'Content-Type': 'application/x-www-form-urlencoded'},
        json=urlencode(data),
        auth=(user.zulip_email, user.zulip_api_key),
        verify=False
    )
    result = response.json()  # 将JSON响应转为字典
except Exception as err:
    return Response(
        {'message': f'Error editing draft: {err}'},
        status=status.HTTP_404_NOT_FOUND,
    )

if result["result"] == 'error':
    return Response(
        {'message': result},
        status=status.HTTP_404_NOT_FOUND
    )
elif result["result"] == 'success':
    response_data = ZulipEditDraftResponse(
        data={
            'result': str(result["result"]),
        }
    )

返回的错误信息:

{
  "message": {
    "result": "error",
    "msg": "Missing 'draft' argument", 
    "var_name":"draft", 
    "code":"REQUEST_VARIABLE_MISSING"
  }
}

使用Postman测试时,最初选raw请求体类型也报错,改为x-www-form-urlencoded后请求成功,对应的curl命令:

curl --location --request PATCH 'http://api.pets.kruts.net/api/v1/zulip/draft/edit/2/' \
--header 'Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjkyMDkzMzM5LCJqdGkiOiJjY2ZlZmNkMmJhNWY0ZWZiYWRlY2Y1ZGQ3NzA3NTMyNSIsInVzZXJfaWQiOjg0OX0.rk4vSSQ_LVT3OQFXuFW21pg1FacKhgRLOHYWdprCnDY' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'email_to=+380635990523@mail.com' \
--data-urlencode 'content=helooo'

已尝试json.dumps和urlencode方法,但问题仍未解决,求Python中正确的请求实现方式。

解决方案

错误原因

代码存在两个核心问题:

  1. 错误使用json参数传递表单数据:json参数会自动将内容序列化为JSON格式并设置Content-Type为application/json,和手动设置的x-www-form-urlencoded头部冲突,导致接口无法识别参数。
  2. 未正确处理嵌套字典的表单编码:urlencode无法直接解析嵌套字典结构,需要将draft下的子参数转为draft[xxx]格式的扁平键值对。

修正后的代码

draft_content = body_serializer.data['content']
recipient_stream_id = user_to.zulip_id
topic = "draft"
draft_type = "private"

# 将嵌套的draft结构转为表单要求的键值对格式
form_data = {
    'draft[content]': draft_content,
    'draft[to][]': recipient_stream_id,  # 数组类型参数需用[]后缀
    'draft[topic]': topic,
    'draft[type]': draft_type
}

try:
    response = requests.patch(
        f'{settings.ZULIP_SITE}api/v1/drafts/{draft_id}',
        # 无需手动设置Content-Type,使用data参数时requests会自动处理
        data=form_data,
        auth=(user.zulip_email, user.zulip_api_key),
        verify=False
    )
    result = response.json()
except Exception as err:
    return Response(
        {'message': f'Error editing draft: {err}'},
        status=status.HTTP_404_NOT_FOUND,
    )

if result["result"] == 'error':
    return Response(
        {'message': result},
        status=status.HTTP_404_NOT_FOUND
    )
elif result["result"] == 'success':
    response_data = ZulipEditDraftResponse(
        data={
            'result': str(result["result"]),
        }
    )

关键说明

  • 参数传递方式:改用data参数传递表单数据,requests会自动完成x-www-form-urlencoded编码,并设置正确的请求头,无需手动指定Content-Type。
  • 嵌套参数处理:Zulip的表单接口要求嵌套参数以draft[xxx]格式传递,数组类型参数需添加[]后缀(如draft[to][]),如果有多个收件ID,可重复添加该键传递多个值。
  • 避免手动编码:直接传递字典给data参数即可,requests会自动调用urlencode完成编码,无需手动处理后再传给json参数。

内容的提问来源于stack exchange,提问作者Andreww_xian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 01:05:17