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

如何用Ajax和Django实现医疗应用的动态多选药品及金额求和功能?

嘿,这个需求在医疗类应用里太实用了,我来一步步给你拆解怎么用 Ajax + Django 实现,保证清晰易懂:

实现步骤拆解

1. Django 后端准备

首先得把后端的数据接口搭好,让前端能拿到药品列表,核心交互逻辑虽然在前端,但后端得先把数据通道打通。

1.1 定义药品模型

先在你的 Django app 里创建药品模型,包含名称和价格两个核心字段:

# models.py
from django.db import models

class Drug(models.Model):
    name = models.CharField(max_length=100, verbose_name="药品名称")
    price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="单价")

    def __str__(self):
        return self.name

记得迁移数据库:python manage.py makemigrations 和 python manage.py migrate,之后可以通过后台或者脚本添加一些测试药品数据。

1.2 编写视图返回药品数据

写一个简单的视图函数,把所有药品数据以 JSON 格式返回,供前端 Ajax 获取:

# views.py
from django.http import JsonResponse
from .models import Drug

def drug_list(request):
    drugs = Drug.objects.all().values('id', 'name', 'price')
    return JsonResponse({'drugs': list(drugs)})

1.3 配置 URL

在 app 的 urls.py 里添加对应路由:

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('drugs/', views.drug_list, name='drug_list'),
    # 其他项目路由...
]

2. 前端页面实现

前端需要完成三个核心功能:加载药品列表、处理选中/取消事件、展示已选药品并计算总和。

2.1 HTML 结构

先搭好页面的基本框架,分成三个功能区域:

<!-- templates/your_template.html -->
<!DOCTYPE html>
<html>
<head>
    <title>药品选择</title>
    <!-- 加个简单样式提升体验 -->
    <style>
        .container {
            display: flex;
            gap: 30px;
            padding: 20px;
            max-width: 1200px;
            margin: 0 auto;
        }
        .drug-selection {
            flex: 1;
            padding: 20px;
            border-right: 1px solid #eee;
        }
        .selected-drugs {
            flex: 1;
            padding: 20px;
        }
        .drug-item {
            margin-bottom: 10px;
            padding: 8px 12px;
            background: #f8f9fa;
            border-radius: 4px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .remove-btn {
            background: #dc3545;
            color: white;
            border: none;
            border-radius: 3px;
            padding: 4px 8px;
            cursor: pointer;
        }
        .checkbox-item {
            margin-bottom: 8px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="drug-selection">
            <h3>药品列表</h3>
            <div id="drug-list"></div> <!-- Ajax动态加载药品checkbox -->
        </div>

        <div class="selected-drugs">
            <h3>已选药品</h3>
            <div id="selected-panel">
                <p style="color: #6c757d;">暂无选中药品</p>
            </div>
            <div style="margin-top: 25px;">
                <label>总金额:</label>
                <input type="text" id="total-amount" readonly value="0.00" style="padding: 6px; width: 100px;">
            </div>
        </div>
    </div>

    <!-- 引入jQuery简化Ajax和DOM操作 -->
    <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
    {% csrf_token %} <!-- Django CSRF令牌,必须加 -->
    <script>
        // 核心交互逻辑写在这里
    </script>
</body>
</html>

2.2 JavaScript 交互逻辑

把下面的代码放到上面的 script 标签里,实现完整交互:

$(document).ready(function() {
    // 配置CSRF令牌,解决Django Ajax跨域问题
    var csrftoken = $("[name=csrfmiddlewaretoken]").val();
    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        }
    });

    // 1. 从后端加载药品列表
    $.ajax({
        url: "{% url 'drug_list' %}", // Django模板标签生成路由
        type: "GET",
        success: function(response) {
            var drugList = $('#drug-list');
            drugList.empty();
            $.each(response.drugs, function(index, drug) {
                var checkboxItem = $('<div>').addClass('checkbox-item')
                    .append($('<input>').attr({
                        type: 'checkbox',
                        class: 'drug-checkbox',
                        'data-id': drug.id,
                        'data-name': drug.name,
                        'data-price': drug.price
                    }))
                    .append(' ' + drug.name + ' - ¥' + drug.price);
                drugList.append(checkboxItem);
            });
        }
    });

    // 2. 监听药品选中/取消事件
    $(document).on('change', '.drug-checkbox', function() {
        var isChecked = $(this).is(':checked');
        var drugId = $(this).data('id');
        var drugName = $(this).data('name');
        var drugPrice = parseFloat($(this).data('price'));

        if (isChecked) {
            // 移除默认提示文字
            if ($('#selected-panel p').length > 0) {
                $('#selected-panel').empty();
            }
            // 添加到已选面板
            var drugItem = $('<div>').addClass('drug-item').attr('data-id', drugId)
                .append('<span>' + drugName + ' - ¥' + drugPrice.toFixed(2) + '</span>')
                .append($('<button>').addClass('remove-btn').text('移除').click(function() {
                    // 移除时同步取消checkbox选中,并重新计算总和
                    $('.drug-checkbox[data-id="' + drugId + '"]').prop('checked', false);
                    $(this).parent().remove();
                    // 如果面板空了,重新显示提示文字
                    if ($('#selected-panel .drug-item').length === 0) {
                        $('#selected-panel').append('<p style="color: #6c757d;">暂无选中药品</p>');
                    }
                    calculateTotal();
                }));
            $('#selected-panel').append(drugItem);
        } else {
            // 从已选面板移除
            $('#selected-panel .drug-item[data-id="' + drugId + '"]').remove();
            // 如果面板空了,重新显示提示文字
            if ($('#selected-panel .drug-item').length === 0) {
                $('#selected-panel').append('<p style="color: #6c757d;">暂无选中药品</p>');
            }
        }

        // 实时计算总金额
        calculateTotal();
    });

    // 3. 计算总金额的工具函数
    function calculateTotal() {
        var total = 0;
        // 遍历所有选中的checkbox累加价格
        $('.drug-checkbox:checked').each(function() {
            total += parseFloat($(this).data('price'));
        });
        // 更新总金额输入框,保留两位小数
        $('#total-amount').val(total.toFixed(2));
    }
});

3. 额外优化建议

  • 数据精度:金额计算用 toFixed(2) 强制保留两位小数,避免浮点数精度误差。
  • 用户体验:可以给选中的药品项添加高亮样式,或者在移除按钮上添加hover效果。
  • 批量操作:如果需要的话,还可以添加“全选”“清空已选”按钮,进一步提升效率。

这样一套流程下来,就能完美实现你要的功能:多选药品、在独立面板展示已选项、实时自动计算总金额~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:02:07