如何在Django views.py中触发模态弹窗判断运单记录是否存在?
Django实现运单ID存在性校验与模态弹窗确认流程
需求概述
用户在运单表单的第一个字段输入shpid后,系统需自动校验该运单是否存在:
- 若不存在,用户可继续填写剩余表单完成新增
- 若存在,弹出确认弹窗,用户确认后切换为更新表单并加载已有运单数据
1. 前端实现实时校验与模态弹窗
在tracker/add_shipment.html模板中添加模态框结构,并通过JavaScript监听shpid输入事件,发起AJAX请求校验运单存在性:
<!-- 运单存在确认模态框 --> <div class="modal fade" id="shipmentExistsModal" tabindex="-1" aria-labelledby="shipmentExistsModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="shipmentExistsModalLabel">运单已存在</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> 该运单ID已存在,是否切换为更新模式? </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="confirmUpdate">确认更新</button> </div> </div> </div> </div> <!-- 原有表单渲染 --> {{ form|crispy }} <script> document.addEventListener('DOMContentLoaded', function() { const shpidInput = document.querySelector('#id_shpid'); const modal = new bootstrap.Modal(document.getElementById('shipmentExistsModal')); let existingShipmentData = null; // 监听shpid输入框失焦事件,发起存在性校验 shpidInput.addEventListener('blur', function() { const shpid = this.value.trim(); if (!shpid) return; fetch(`/check-shipment-exists/?shpid=${shpid}`) .then(response => response.json()) .then(data => { if (data.exists) { existingShipmentData = data.shipment; modal.show(); } }); }); // 确认更新:填充表单数据并切换为更新模式 document.getElementById('confirmUpdate').addEventListener('click', function() { if (!existingShipmentData) return; // 遍历填充所有字段 Object.keys(existingShipmentData).forEach(key => { const field = document.querySelector(`#id_${key}`); if (field) { if (field.type === 'date') { field.value = existingShipmentData[key] ? existingShipmentData[key].split('T')[0] : ''; } else { field.value = existingShipmentData[key]; } } }); // 设置shpid为只读 shpidInput.setAttribute('readonly', true); shpidInput.style.backgroundColor = 'gainsboro'; // 修改提交按钮文本 const submitBtn = document.querySelector('button[type="submit"]'); if (submitBtn) submitBtn.textContent = 'Update Shipment'; modal.hide(); }); }); </script>
2. 后端新增运单存在性校验API
在views.py中新增视图函数,处理前端的校验请求,返回JSON格式结果:
from django.http import JsonResponse from .models import Shipment from django.views.decorators.http import require_GET @require_GET def check_shipment_exists(request): shpid = request.GET.get('shpid', '') if not shpid: return JsonResponse({'exists': False}) try: shipment = Shipment.objects.get(shpid=shpid) # 序列化运单数据为JSON格式 shipment_data = { 'shpid': shipment.shpid, 'awb': shipment.awb, 'pod': shipment.pod, 'coldate': shipment.coldate.isoformat() if shipment.coldate else None, 'deldate': shipment.deldate.isoformat() if shipment.deldate else None, 'recipient': shipment.recipient, 'status': shipment.status, 'sts_date': shipment.sts_date.isoformat() if shipment.sts_date else None, 'costs': str(shipment.costs) } return JsonResponse({'exists': True, 'shipment': shipment_data}) except Shipment.DoesNotExist: return JsonResponse({'exists': False})
在urls.py中添加对应路由:
from django.urls import path from . import views urlpatterns = [ # 原有运单添加/更新路由 path('add-shipment/<int:pk>/<str:orderid>/', views.add_shipment, name='add_shipment'), # 新增运单存在性校验路由 path('check-shipment-exists/', views.check_shipment_exists, name='check_shipment_exists'), ]
3. 调整原有视图逻辑
修改add_shipment视图,支持新增和更新两种场景,处理用户确认更新后的表单提交:
from .forms import AddShpForm, UpdateShpForm from django.contrib import messages from django.shortcuts import redirect, render, get_object_or_404 def add_shipment(request, pk, orderid): order = get_object_or_404(Order, pk=pk) if request.method == 'POST': shpid = request.POST.get('shpid') try: # 运单存在,使用更新表单处理 shipment = Shipment.objects.get(shpid=shpid) form = UpdateShpForm(request.POST, instance=shipment) if form.is_valid(): form.save() order.shipment = shipment order.save() messages.success(request, f'Shipment: {shpid} - updated and attached to Order: {order.orderid}') return redirect('tracker:list_orders', 'open') except Shipment.DoesNotExist: # 运单不存在,使用新增表单处理 form = AddShpForm(request.POST) if form.is_valid(): shipment = form.save() order.shipment = shipment order.save() messages.success(request, f'Shipment: {shpid} - saved and attached to Order: {order.orderid}') return redirect('tracker:list_orders', 'open') # 表单验证失败,返回当前表单 return render(request, 'tracker/add_shipment.html', {'form': form}) else: # GET请求默认返回新增表单 form = AddShpForm() return render(request, 'tracker/add_shipment.html', {'form': form})
4. 完善UpdateShpForm定义
确保UpdateShpForm正确继承并设置shpid为只读:
from django.forms import ModelForm, TextInput, DateInput from .models import Shipment from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout, Row, Column, Field, ButtonHolder, Submit class UpdateShpForm(ModelForm): class Meta: model = Shipment fields = '__all__' widgets = { "shpid": TextInput(attrs={'readonly': True, 'style': 'max-width:120px; background-color:gainsboro'}), "costs": TextInput(attrs={'style': 'max-width:200px'}), "coldate": DateInput(attrs={'type': 'date', 'style': 'max-width:180px'}), "deldate": DateInput(attrs={'type': 'date', 'style': 'max-width:180px'}), "sts_date": DateInput(attrs={'type': 'date', 'style': 'max-width:180px'}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 统一字段标签和布局 self.fields['shpid'].label = "Shipment ID" self.fields['awb'].label = "AWB" self.fields['pod'].label = "POD" self.fields['coldate'].label = "Collection Date" self.fields['deldate'].label = "Delivery Date" self.fields['recipient'].label = "Recipient" self.fields['status'].label = "Status" self.fields['sts_date'].label = "Status Date" self.fields['costs'].label = "Costs" self.helper = FormHelper() self.form_method = 'post' self.helper.layout = Layout( Row ( Column('shpid', css_class='form-group col-md-2 mb-0 pe-4'), Column('status', css_class='form-group col-md-4 mb-0 ps-2 pe-2'), Column('sts_date', css_class='form-group col-md-4 mb-0 ps-4'), ), Row( Column('awb', css_class='form-group col-md-6 mb-0 pe-4'), Column('pod', css_class='form-group col-md-6 mb-0 pe-4'), ), Row( Column('coldate', css_class='form-group col-md-3 mb-0 pe-4'), Column('deldate', css_class='form-group col-md-3 mb-0 ps-2 pe-2'), Column('recipient', css_class='form-group col-md-6 mb-0 ps-4 pe-4'), ), Field('costs'), ButtonHolder( Submit('submit', 'Update Shipment', css_class='ml-n2 btn-lg fw-bolder'), css_class='center' ) )
内容的提问来源于stack exchange,提问作者Doug Conran
相关产品推荐
相关产品推荐

