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

如何通过Django REST Framework发送XML转换得到的JSON数据

DRF返回第三方接口转换后数据的解决方案

首先明确:你代码中xmltodict.parse(x.text)返回的js变量是Python字典对象,不是JSON字符串,DRF原生支持将Python字典、列表等结构直接转换为JSON响应,无需额外序列化模型,以下提供两种常用实现方案:


方案1:直接透传供应商数据(无需本地存储)

适合不需要保存商品数据、每次请求都要获取最新供应商数据的场景,直接在DRF视图中调用拉取逻辑后返回数据即可:

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
import requests
import xmltodict
from django.conf import settings

class SupplierProductView(APIView):
    def get(self, request):
        # 敏感配置建议放到settings或环境变量,不要硬编码
        url = settings.SUPPLIER_API_URL
        headers = {'content-type': 'text/xml'}
        raw_data = """<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetCTProducts xmlns="http://www.partnerURL.com/B2B">
      <username>{username}</username>
      <password>{password}</password>
    </GetCTProducts>
  </soap:Body>
</soap:Envelope>""".format(username=settings.SUPPLIER_USER, password=settings.SUPPLIER_PWD)
        
        try:
            # 加超时避免请求卡住
            resp = requests.post(url, data=raw_data, headers=headers, timeout=15)
            resp.raise_for_status()
            product_data = xmltodict.parse(resp.text)
            # 可在此处过滤不需要的字段后再返回
            return Response(product_data)
        except Exception as e:
            return Response({"error": "拉取商品数据失败"}, status=500)

随后在urls.py中配置对应路由即可,前端请求该路由就能拿到JSON格式的商品数据。


方案2:同步到本地模型后返回(推荐,适合商城场景)

商城场景通常需要自定义商品字段、缓存数据避免每次请求第三方接口,建议先把供应商数据同步到本地Django模型,再通过DRF序列化返回:

步骤1:创建商品模型

# models.py
from django.db import models

class Product(models.Model):
    sku = models.CharField(max_length=64, unique=True, verbose_name="商品唯一编码")
    name = models.CharField(max_length=255, verbose_name="商品名称")
    price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="售价")
    stock = models.IntegerField(default=0, verbose_name="库存")
    description = models.TextField(blank=True, verbose_name="商品描述")
    last_sync_time = models.DateTimeField(auto_now=True, verbose_name="最后同步时间")

步骤2:创建序列化器

# serializers.py
from rest_framework import serializers
from .models import Product

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ["sku", "name", "price", "stock", "description"]

步骤3:编写数据同步逻辑

可封装为Django管理命令、定时任务(Celery/Django-Q)定期执行:

def sync_products():
    # 此处复用上面的拉取供应商数据逻辑,拿到product_data字典
    # 按供应商实际返回的XML嵌套结构,取出商品列表
    supplier_product_list = product_data["soap:Envelope"]["soap:Body"]["GetCTProductsResponse"]["ProductList"]["Product"]
    for item in supplier_product_list:
        # 字段映射根据实际返回结构调整
        Product.objects.update_or_create(
            sku=item["SKU"],
            defaults={
                "name": item["ProductName"],
                "price": item["SalePrice"],
                "stock": item["StockCount"],
                "description": item.get("ProductDesc", "")
            }
        )

步骤4:编写返回商品列表的视图

# views.py
from rest_framework.generics import ListAPIView
from .models import Product
from .serializers import ProductSerializer

class ProductListView(ListAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

配置路由后前端请求该接口即可拿到本地存储的商品数据,响应速度比直接请求第三方接口快很多,也支持添加自定义业务逻辑(比如商品分类、标签筛选)。


注意事项

  • 第三方接口调用要加异常捕获、超时设置,避免影响本站接口可用性
  • 供应商账号密码、接口地址等敏感信息不要硬编码,建议存到环境变量或Django settings配置中
  • 若供应商接口有调用频率限制,必须使用本地同步缓存的方案,避免触发限流

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 04:45:09