#python #django #leaflet #geodjango
#python #джанго #брошюра #geodjango
Вопрос:
У меня есть проект Django с таким макетом
в urls.py
from django.contrib import admin
from django.conf.urls import url as path
from mapping import views
urlpatterns = [
path('admin/', admin.site.urls),
path('map/', views.Map, name='map'),
path('address',views.Address_Search,name='address')
]
views.py
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse,HttpResponse
import geocoder
import pdb
bingkey='mykey'
def Map(request):
return render(request,'mapping.html')
@csrf_exempt
def Address_Search(request):
try:
address=request.POST.get('fname')
print(address)
g = geocoder.bing(address,key=bingkey)
x,y= g.latlng[1],g.latlng[0]
print(x,y)
return JsonResponse({'id': 1,'x': x, 'y': y,'Address': address})
except Exception as e:
print(e)
return render(request,'mapping.html')
и в шаблонах у меня есть mapping.html который содержит
{% block content %}
<html>
{% load static %}
{% load leaflet_tags %}
{% load bootstrap4 %}
<head>
{% leaflet_js %}
{% leaflet_css %}
{% bootstrap_css %}
<title>Sals Food</title>
<style type="text/css">
#map {width: 100%;height:800px;}
</style>
<link rel="stylesheet" type="text/css" href="{% static 'search_bar.css' %}">
<link rel="stylesheet" href="{% static 'bootstrap-4.0.0-dist/css/bootstrap.css' %}" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Poppins" rel="stylesheet" />
<script type="text/javascript" src="{% static 'jquery/jquery-3.3.1.min.js' %}" > </script>
<script type="text/javascript" src="{% static 'dist/leaflet.ajax.js' %}" > </script>
<script type="text/javascript" src="{% static 'turf/turf.min.js' %}" > </script>
<script type="text/javascript" src="{% static 'basemaps/leaflet-providers.js' %}" > </script>
<script>
function subForm()
{
var jsdata = {"fname": $('#fname').val()};
console.log(jsdata);
var url = "/address/";
var jqHdr = $.ajax({
async: true,
cache: false,
type: "POST",
url: url,
data: jsdata,
dataType: "json"
}).done(function (data, textStatus) {
if (data.id == 1)
{
console.log("Longitude: " data.x " Latitude: " data.y " Address " data.Address );
$('#map').remove();
var t = $("<div id='map'></div>");
$("body").append(t);
createmap(data.x,data.y,data.Address);
}
});
}
function createmap(x,y,address){
var map = L.map('map');
map.setView([40.70,-73.90], 11);
var boros = new L.GeoJSON.AJAX("../static/boros.geojson",{
onEachFeature: function(feature,layer){
layer.bindPopup(feature.properties.boro_name)
}
});
boros.addTo(map);
L.marker([y, x]).addTo(map).bindPopup(address);
lyrOSM = L.tileLayer.provider('OpenStreetMap.Mapnik');
lyrESRIWSM = L.tileLayer.provider('Esri.WorldStreetMap');
lyrESRITopo = L.tileLayer.provider('Esri.WorldTopoMap');
lyrESRIImagery = L.tileLayer.provider('Esri.WorldImagery').addTo(map);
objBaseMaps = {
"Street - OSM":lyrOSM,
"Street - ESRI":lyrESRIWSM,
"Imagery - ESRI Imagery":lyrESRIImagery,
"Topo - ESRI Topo":lyrESRITopo,
};
ctlLayers = L.control.layers(objBaseMaps,{}, {sortLayers:true}).addTo(map);
}
</script>
</head>
<body>
<div class="s01">
<form action="/address/" method="post">
<div class="inner-form">
<div class="input-field second-wrap">
<input type="text" id="fname" name="fname" value="Enter a address">
</div>
<div class="input-field third-wrap">
<button class="btn-search" onclick="subForm()" type="button">Search</button>
</div>
</div>
</form>
</div>
</body>
</html>
{% endblock %}
Как это работает
Пользователь вводит адрес http://localhost:8000/map/
, подобный этому
введенный адрес помещается в форму POST-запроса html и использует AJAX для передачи POST-запроса в view.py Адресный поиск. Адрес геокодируется и возвращает x, y и адрес обратно на страницу. Для этого примера это работает хорошо, поскольку вы можете видеть, что вывод правильный. [3]: https://i.stack.imgur.com/hKYU3.jpg [![введите описание изображения здесь][3]][3]
Проблема
Бывают случаи, когда я ввожу неправильный адрес или просто случайные буквы
например, я только что ввел, 55 water street
и это то, что возвращается. Он не выдает ошибку в представлении Address_Search, он геокодирует входные данные, но по какой-то причине он перенаправляет http://localhost:8000/address/
большую часть времени, если адрес точный, этого не происходит, вот почему я очень смущен. Должно быть, у меня здесь что-то не так…
// 20210120180356
// http://localhost:8000/address/
{
"id": 1,
"x": -74.00910186767578,
"y": 40.70320129394531,
"Address": "55 water street"
}
Комментарии:
1. Видите ли вы какие-либо ошибки, напечатанные в командной строке, в которой запущен сервер?
2. нет никаких ошибок — когда он выдает ошибку, он правильно отобразит mapping.html страница назад
3. Основываясь на возврате в исключении, я предполагаю, что ошибка выдается и, возможно, просто теряется в миксе. Попробуйте изменить возврат исключения на json вместо рендеринга, как в вашем
try
. Что-то вроде:return JsonResponse({"error": "error"})
просто чтобы проверить это4. Я вошел
a fake address blah blah
и получил это обратно// http://localhost:8000/address/ { "id": 1, "x": 9.539226531982422, "y": 11.746624946594238, "Address": "a fake address blah blah" }
5. и я изменил то, что вы рекомендовали
Ответ №1:
Похоже, где-то в address api есть ошибка. Я бы покопался в этом на стороне django и посмотрел, что является причиной этого. Но когда выдается эта ошибка, вы используете render
, который будет отображать предоставленный вами html-шаблон и перенаправлять страницу. Поскольку вы вызываете /address/
и разрешаете перенаправление страницы, она перенаправляется на этот URL-адрес.
Вместо этого вы можете изменить ответ на ответ json. Я бы изменил оба параметра try и catch и включил status
бы пару ключ-значение, а также нужные вам данные.
@csrf_exempt
def Address_Search(request):
try:
address=request.POST.get('fname')
print(address)
g = geocoder.bing(address,key=bingkey)
x,y= g.latlng[1],g.latlng[0]
print(x,y)
return JsonResponse({'status': 'success', 'data': {'id': 1,'x': x, 'y': y,'Address': address}})
except Exception as e:
print(e)
return JsonResponse({'status': 'error', 'error': e})
Вы могли бы даже немного его очистить, в частности, с помощью одного JsonResponse:
@csrf_exempt
def Address_Search(request):
response = {'status': None,
'data': None,
'error': None,
}
try:
address=request.POST.get('fname')
print(address)
g = geocoder.bing(address,key=bingkey)
x,y= g.latlng[1],g.latlng[0]
print(x,y)
response['status'] = 'success'
response['data'] = {'id': 1,'x': x, 'y': y,'Address': address}
except Exception as e:
print(e)
response['status'] = 'error'
response['error'] = e
return JsonResponse(response)
Это может потребовать некоторой очистки, поскольку я просто набираю SO, но это общая идея
редактировать — Кроме того, это приведет к некоторым изменениям на стороне javascript — вам нужно будет искать статус ошибки и обрабатывать его, а также получать данные из значения данных, а не только из самого возвращаемого объекта.
редактировать 2 — Убедитесь, что форма фактически не отправляется при нажатии кнопки (она обрабатывается как кнопка отправки, даже если вы этого явно не сказали). Вы можете добавить onsubmit="return false;"
в саму форму или в конце вашего done
метода в jquery добавить return false;
Комментарии:
1. внес ваши изменения, но у меня все еще та же проблема … введен
what is you problem
, и он перенаправляет меня на адрес url следующим образом// http://localhost:8000/address/ { "status": "success", "data": { "id": 1, "x": 57.900001525878906, "y": 57.04999923706055, "Address": "what is your problem" }, "error": null }
2. а затем я вернулся на страницу, отправленную повторно, и отобразил URL-адрес карты. Я думаю, может быть, это API геокодирования? или, может быть, это что-то с тем, как я настраиваю свои URL-адреса django и как он подключается к форме HTML POST
3. А как насчет:
return JsonResponse(json.dumps(response))
Вам тоже нужноimport json
подняться наверх4. Одна мысль, которая пришла мне в голову прошлой ночью, которая не связана с моим ответом (но я поддерживаю изменения в моем ответе!), заключается в том, чтобы
return false
включитьsubForm
— это может быть отправка формы, и это вызывает перенаправление.5. похоже, это сработало! Я не видел, что происходило раньше, примерно за 50 попыток. добавьте это к своему ответу, и я приму. Спасибо!