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

Django/Python中API视图测试页面构建技术求助

嘿,我来帮你搞定这些Django API的测试页面构建问题!针对你给出的三个APIView类,我整理了从简单到进阶的几种实用测试方案,你可以根据自己的需求来选:

一、最省心的快速测试:用DRF自带的可视化文档

Django REST Framework(DRF)本身就带了开箱即用的API可视化界面,不用写任何前端代码就能测试,步骤超简单:

  1. 先确保你的settings.py里已经注册了rest_framework:
INSTALLED_APPS = [
    # 你的其他应用...
    'rest_framework',
]
  1. 在项目的urls.py里添加DRF的文档路由:
from django.urls import path
from rest_framework.documentation import include_docs_urls

urlpatterns = [
    # 你的API路由(比如/api/user-profile/这类)...
    path('api-docs/', include_docs_urls(title='Fuel API 测试文档')),
]
  1. 启动Django服务后,访问http://localhost:8000/api-docs/就能看到所有API的可视化界面。因为你的API要求登录认证,先登录Django后台,再回到这个页面就能直接发送GET/PUT/POST请求,还能自动带上认证信息,完美适配你的权限要求。
二、自定义简单测试页面(适合基础调试)

如果想要自己写一个轻量化的测试页面,这里给你一个原生HTML+JS的示例,直接放在Django模板里就能用:

首先创建模板文件templates/test_api.html:

<!DOCTYPE html>
<html>
<head>
    <title>燃油API测试控制台</title>
    <style>
        .test-block { margin: 2rem 0; padding: 1.5rem; border: 1px solid #eee; border-radius: 8px; }
        button { padding: 0.5rem 1rem; margin: 0.5rem; cursor: pointer; }
        .result { margin-top: 1rem; padding: 1rem; background-color: #f8f9fa; border-radius: 4px; white-space: pre-wrap; }
        input { margin: 0.3rem; padding: 0.3rem; }
    </style>
</head>
<body>
    <h1>燃油API测试控制台</h1>

    <!-- 用户信息测试区块 -->
    <div class="test-block">
        <h2>用户信息接口</h2>
        <button onclick="fetchProfile()">获取当前用户信息</button>
        <div class="result" id="profile-result"></div>

        <h3>更新用户信息</h3>
        <input type="text" id="full_name" placeholder="全名" value="张三">
        <input type="text" id="address1" placeholder="地址1" value="北京市朝阳区XX路">
        <input type="text" id="address2" placeholder="地址2" value="XX小区1号楼">
        <input type="text" id="city" placeholder="城市" value="北京">
        <input type="text" id="state" placeholder="省份" value="BJ">
        <input type="text" id="zipcode" placeholder="邮编" value="100020">
        <button onclick="updateProfile()">提交更新</button>
        <div class="result" id="update-result"></div>
    </div>

    <!-- 报价历史测试区块 -->
    <div class="test-block">
        <h2>报价历史接口</h2>
        <button onclick="fetchQuotes()">获取报价历史</button>
        <div class="result" id="quotes-result"></div>

        <h3>提交新报价</h3>
        <input type="number" id="gallons" placeholder="加油量(加仑)" value="800">
        <input type="text" id="delivery_address" placeholder="配送地址" value="北京市朝阳区XX路">
        <input type="date" id="delivery_date" value="2024-12-15">
        <input type="number" id="price" placeholder="单价" value="2.6">
        <input type="number" id="amount_due" placeholder="总金额" value="2080">
        <button onclick="submitQuote()">提交报价</button>
        <div class="result" id="submit-result"></div>
    </div>

    <!-- 价格计算测试区块 -->
    <div class="test-block">
        <h2>价格计算接口</h2>
        <input type="number" id="calc_gallons" placeholder="加油量(加仑)" value="1200">
        <button onclick="calculatePrice()">计算价格</button>
        <div class="result" id="price-result"></div>
    </div>

    <script>
        // 处理Django的CSRF Token,POST/PUT请求必须带这个
        function getCookie(name) {
            let value = null;
            if (document.cookie && document.cookie !== '') {
                const cookies = document.cookie.split(';');
                for (let i = 0; i < cookies.length; i++) {
                    const cookie = cookies[i].trim();
                    if (cookie.substring(0, name.length + 1) === (name + '=')) {
                        value = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return value;
        }
        const csrftoken = getCookie('csrftoken');

        // 获取用户信息
        async function fetchProfile() {
            const res = await fetch('/api/user-profile/', {
                method: 'GET',
                credentials: 'include'
            });
            const data = await res.json();
            document.getElementById('profile-result').textContent = JSON.stringify(data, null, 2);
        }

        // 更新用户信息
        async function updateProfile() {
            const data = {
                full_name: document.getElementById('full_name').value,
                address1: document.getElementById('address1').value,
                address2: document.getElementById('address2').value,
                city: document.getElementById('city').value,
                state: document.getElementById('state').value,
                zipcode: document.getElementById('zipcode').value
            };
            const res = await fetch('/api/user-profile/', {
                method: 'PUT',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': csrftoken
                },
                credentials: 'include',
                body: JSON.stringify(data)
            });
            const resData = await res.json();
            document.getElementById('update-result').textContent = JSON.stringify(resData, null, 2);
        }

        // 获取报价历史
        async function fetchQuotes() {
            const res = await fetch('/api/quotes-history/', {
                method: 'GET',
                credentials: 'include'
            });
            const data = await res.json();
            document.getElementById('quotes-result').textContent = JSON.stringify(data, null, 2);
        }

        // 提交新报价
        async function submitQuote() {
            const data = {
                gallons: parseInt(document.getElementById('gallons').value),
                delivery_address: document.getElementById('delivery_address').value,
                delivery_date: document.getElementById('delivery_date').value,
                price: parseFloat(document.getElementById('price').value),
                amount_due: parseFloat(document.getElementById('amount_due').value)
            };
            const res = await fetch('/api/quotes-history/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': csrftoken
                },
                credentials: 'include',
                body: JSON.stringify(data)
            });
            const resData = await res.json();
            document.getElementById('submit-result').textContent = JSON.stringify(resData, null, 2);
        }

        // 计算价格
        async function calculatePrice() {
            const gallons = parseInt(document.getElementById('calc_gallons').value);
            const res = await fetch('/api/get-price/', {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': csrftoken
                },
                credentials: 'include',
                body: JSON.stringify({ gallons: gallons })
            });
            const data = await res.json();
            document.getElementById('price-result').textContent = JSON.stringify(data, null, 2);
        }
    </script>
</body>
</html>

然后在urls.py里添加路由渲染这个模板:

from django.views.generic import TemplateView

urlpatterns = [
    # 其他路由...
    path('test-api/', TemplateView.as_view(template_name='test_api.html'), name='test_api'),
]

注意:测试前要先登录Django后台,确保页面能带上认证的Session Cookie。

三、进阶专业测试:用Postman/Insomnia

如果需要更强大的测试功能(比如保存请求集合、批量测试、环境变量),可以用Postman或者Insomnia:

  1. 配置认证:先发送GET请求到/admin/login/,登录后工具会自动保存Session Cookie,后续的API请求都会带上认证信息。
  2. 创建对应请求:
    • GET /api/user-profile/:获取用户信息
    • PUT /api/user-profile/:选择JSON格式的请求体,填入要更新的字段
    • GET /api/quotes-history/:获取报价历史
    • POST /api/quotes-history/:JSON请求体填入报价字段
    • GET /api/get-price/:JSON请求体填入gallons参数
四、你的API代码优化建议(减少测试踩坑)

测试前可以给API做几个小优化,让调试更顺畅:

  1. 不要用笼统的异常捕获:你现在的except:会吞掉所有错误,很难定位问题,改成捕获具体异常:
def put(self, request):
    try:
        # 原代码逻辑...
    except KeyError as e:
        return Response({'error': f'缺少必填字段:{str(e)}'}, status=400)
    except ClientInformation.DoesNotExist:
        return Response({'error': '未找到用户信息'}, status=404)
    except Exception as e:
        return Response({'error': f'更新失败:{str(e)}'}, status=500)
  1. 统一用DRF的Response代替JsonResponse:Response会自动处理内容协商,比JsonResponse更适配API场景,比如UserProfile的get方法可以改成:
def get(self, request):
    user = request.user
    client_info = ClientInformation.objects.filter(user_id=user.id).values(
        'full_name', 'address1', 'address2', 'city', 'state', 'zipcode'
    ).first()
    if not client_info:
        return Response({'error': '未找到用户信息'}, status=404)
    return Response(client_info)
  1. GetPrice的GET请求用query_params:REST规范中GET参数应该放在URL里,而不是请求体,修改后更符合规范也方便测试:
def get(self, request):
    user = request.user
    gallons = int(request.query_params.get('gallons'))
    # 原逻辑...

测试时可以直接用/api/get-price/?gallons=1000这种URL参数方式调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 17:09:05