如何在Django中实现Ajax校验日期冲突后确认保存功能
需求
点击表单提交按钮时,通过Ajax检查数据库中是否存在日期交集;仅当用户确认仍要添加时,才将数据保存至数据库并跳转至其他页面。当前仅实现了弹出alert提示的功能。
现有代码
Komandirov_add.html
<form method="post" id="contactForm"> {% csrf_token %} {% if form.warnings %} <div class="rounded p-2 mt-2 bg-warning"> <ul> {% for warning in form.warnings %} <li><b>{{ warning.message }}:</b> {{ warning.description }}</li> {% endfor %} </ul> </div> {% endif %} <div style="display: flex;flex-wrap: wrap;"> {{ form.NumberKU.label_tag }}{{ form.NumberKU }} {% if form.NumberKU.errors %} <div class="error">{{ form.NumberKU.errors }}</div> {% endif %} </div> <input id='d' type="submit" onclick="reload_page(); return false;" value="Сохранить"> </form> <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script> $(document).ready(function () { $('#contactForm').submit(function () { $.ajaxSetup({ headers: { "X-CSRFToken": document.querySelector('[name=csrfmiddlewaretoken]').value, } }); $.ajax({ data: $(this).serialize(), url: "{% url 'prikaz:komandirov_add' human.pk %}", type: $(this).attr('method'), success: function (response) { console.log(response.f) if (response.f == 'f') { alert('dd'); window.location.href = "{% url 'prikaz:komandirov' human.pk %}"; } else{ window.location.href = "{% url 'prikaz:komandirov' human.pk %}"; } }, }); return false; }); }) </script>
urls.py
urlpatterns = [ path('human/<int:id>/komandirov/komandirov_add/', views.KomandirovAdd.as_view(), name='komandirov_add'), ]
views.py
class KomandirovAdd(FormView): form_class = KomandirovForm template_name = 'prikaz/block_content/Komandirov_add.html' # context_object_name = 'form' def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['human'] = Privatedata.objects.get(id=self.kwargs['id']) return context def form_valid(self, form): print(form.cleaned_data) addindb = form.save(commit=False) addindb.People = Privatedata.objects.get(id=self.kwargs['id']) addindb.save() overlapping_records = Otpysk.objects.filter( Q(DateUbitie__range=(form.cleaned_data['DateUbitie'], form.cleaned_data['DataPredpol'])) & Q( DataPredpol__range=(form.cleaned_data['DateUbitie'], form.cleaned_data['DataPredpol']))) if len(overlapping_records) > 0: return JsonResponse({'f':'f'}) else: return JsonResponse({'f':'d'}) def get_success_url(self): return reverse_lazy("prikaz:komandirov", args=[self.kwargs['id']])
修改方案
前端修改
- 替换alert为确认对话框,根据用户选择决定是否提交强制保存请求:
$(document).ready(function () { $('#contactForm').submit(function (e) { e.preventDefault(); const form = $(this); $.ajaxSetup({ headers: { "X-CSRFToken": document.querySelector('[name=csrfmiddlewaretoken]').value, } }); // 第一步:检查日期交集 $.ajax({ data: form.serialize(), url: "{% url 'prikaz:komandirov_add' human.pk %}", type: form.attr('method'), dataType: 'json', success: function (response) { if (response.has_overlap) { // 弹出确认框询问用户 const confirmSave = confirm('检测到日期交集,是否仍要添加该记录?'); if (confirmSave) { // 用户确认,携带强制保存参数重新提交 $.ajax({ data: form.serialize() + '&force_save=true', url: "{% url 'prikaz:komandirov_add' human.pk %}", type: form.attr('method'), success: function () { window.location.href = "{% url 'prikaz:komandirov' human.pk %}"; } }); } // 用户取消则不执行任何操作 } else { // 无交集,直接跳转 window.location.href = "{% url 'prikaz:komandirov' human.pk %}"; } }, }); }); })
- 移除提交按钮上的冲突事件:
<input id='d' type="submit" value="Сохранить">
后端修改
- 调整逻辑,先检查交集再根据参数决定是否保存,同时修正交集查询逻辑:
from django.http import JsonResponse class KomandirovAdd(FormView): form_class = KomandirovForm template_name = 'prikaz/block_content/Komandirov_add.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['human'] = Privatedata.objects.get(id=self.kwargs['id']) return context def form_valid(self, form): # 修正日期交集查询逻辑,用|代替&才能正确检测重叠 overlapping_records = Otpysk.objects.filter( Q(DateUbitie__range=(form.cleaned_data['DateUbitie'], form.cleaned_data['DataPredpol'])) | Q(DataPredpol__range=(form.cleaned_data['DateUbitie'], form.cleaned_data['DataPredpol'])) ) has_overlap = len(overlapping_records) > 0 # 第一次请求仅返回交集状态,不保存数据 if 'force_save' not in self.request.POST: return JsonResponse({'has_overlap': has_overlap}) # 有强制保存参数时,执行保存 addindb = form.save(commit=False) addindb.People = Privatedata.objects.get(id=self.kwargs['id']) addindb.save() return JsonResponse({'success': True})
内容的提问来源于stack exchange,提问作者Hicci Tim
相关产品推荐
相关产品推荐

