如何阻止地理定位重复提交?犯罪预警网站提交异常排查
解决犯罪预警网站重复提交(含/不含经纬度双记录)问题
当前开发的犯罪预警网站存在重复提交问题——用户点击提交后,会生成两条预警记录:一条带有效经纬度,一条经纬度为None。
预期输出(单条有效记录)
lucas posted a crime alert! Alert!!! cv !!! Crime reported from Ogbia, Bayelsa Crime coordinates: Longitude 3.325952 | Latitude 6.599475 Category: c March 9, 2023, 1:53 p.m.
实际输出(重复双记录)
lucas posted a crime alert! Alert!!! cv !!! Crime reported from Ogbia, Bayelsa Crime coordinates: Longitude 3.325952 | Latitude 6.599475 Category: c March 9, 2023, 1:53 p.m. lucas posted a crime alert! Alert!!! cv !!! Crime reported from Ogbia, Bayelsa Crime coordinates: Longitude None | Latitude None Category: c March 9, 2023, 1:53 p.m.
现有代码
Django Views 代码
def new_alert(request): if request.method == "POST": content = request.POST.get("content") state = request.POST.get("state") lga = request.POST.get("lga") category = request.POST.get("category") current_user = request.user lat = request.POST.get("lat") lng = request.POST.get("lng") # Create a new alert new_alert = Alert(content=content, state=state, lga=lga, user=current_user, category=category, latitude=lat, longitude=lng) new_alert.save() return HttpResponseRedirect(reverse("all_alerts")) else: return render(request, "new_alert.html")
JavaScript 代码
<script> function getLocation() { if (navigator.geolocation) { // Display confirmation prompt if (confirm("Allow this website to access your location?")) { navigator.geolocation.getCurrentPosition(sendLocation); } else { alert("Location access denied."); } } else { alert("Geolocation is not supported by this browser."); } } function sendLocation(position) { var lat = position.coords.latitude; var lng = position.coords.longitude; console.log("Sending data: ", { lat: lat, lng: lng }); // Get the CSRF token from the form var csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value; // Get the form data using FormData var form_data = new FormData(document.querySelector('#form-id')); // Add the lat and lng values to the form data form_data.append('lat', lat); form_data.append('lng', lng); // Send the AJAX request with the form data $.ajax({ url: 'new_alert', type: 'POST', data: form_data, contentType: false, processData: false, beforeSend: function (xhr) { xhr.setRequestHeader('X-CSRFToken', csrftoken); }, error: function (xhr, status, error) { alert('Fill the fields before submitting Alert'); } }); } </script>
HTML 代码(移除下拉选项后)
<form id="form-id" action="{% url 'new_alert' %}" method="POST"> {% csrf_token %} <div class="form-group"> <textarea id="create-post-text" name="content" placeholder="Report crime" required></textarea> </div> <div class="form-group"> <label class="control-label">Where Are You Reporting From?</label> </div> <div class="form-group"> <label class="control-label">LGA of Origin</label> <select name="lga" id="lga" class="form-control select-lga" required> </select> </div> <div class="form-group"> <input class="form-control" name="category" placeholder="Specify a category. For example, murder, theft, vandalism, etc" required> </div> <button onclick="getLocation()" class="btn btn-success" id="sendLocation">Alert!</button> </form>
问题根源
按钮默认是submit类型,点击时同时触发两个动作:
- 执行
onclick中的getLocation(),通过AJAX提交带经纬度的表单数据; - 触发表单默认提交行为,直接提交无经纬度的原始表单,生成
None记录。
解决步骤
1. 阻止按钮的默认表单提交行为
推荐直接修改按钮类型为button,避免默认提交:
<button type="button" onclick="getLocation()" class="btn btn-success" id="sendLocation">Alert!</button>
也可以在onclick中返回false阻止默认行为:
<button onclick="getLocation(); return false;" class="btn btn-success" id="sendLocation">Alert!</button>
2. 优化AJAX提交后的页面跳转
AJAX请求不会自动触发Views中的重定向,需在回调中手动跳转:
$.ajax({ url: 'new_alert', type: 'POST', data: form_data, contentType: false, processData: false, beforeSend: function (xhr) { xhr.setRequestHeader('X-CSRFToken', csrftoken); }, success: function() { // 提交成功后跳转到预警列表页 window.location.href = "{% url 'all_alerts' %}"; }, error: function (xhr, status, error) { alert('Fill the fields before submitting Alert'); } });
3. 可选:处理用户拒绝定位的情况
如果需要允许用户拒绝定位后仍提交预警,可修改getLocation函数:
function getLocation() { if (navigator.geolocation) { if (confirm("Allow this website to access your location?")) { navigator.geolocation.getCurrentPosition(sendLocation); } else { alert("Location access denied. You can still submit the alert without location data."); // 手动提交无经纬度的表单 document.querySelector('#form-id').submit(); } } else { alert("Geolocation is not supported by this browser."); document.querySelector('#form-id').submit(); } }
内容的提问来源于stack exchange,提问作者Lukman Samson
相关产品推荐
相关产品推荐

