如何通过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
相关产品推荐
相关产品推荐

