Представление Django иногда перенаправляет на неправильный URL

#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 попыток. добавьте это к своему ответу, и я приму. Спасибо!