MultiValueDictKeyError в / connect / - PullRequest
       8

MultiValueDictKeyError в / connect /

0 голосов
/ 15 февраля 2019

Я пытаюсь использовать все функции определения местоположения на одной странице, например get users location, post it to the database, а затем filter results на основе введенного пользователем значения радиуса в километрах.

Я получаю MultiValueDictKeyError at /connect/ 'latitude' потому что запрос POST собирается

location = Location(latitude=request.POST['latitude'], longitude=request.POST['longitude'], user = request.user)

, когда он должен идти

if request.POST['radius']:
            radius_km = request.POST.get('radius', 0)

Я исследовал, как остановить это, и увидел, что могу сделать if request.POST['radius']:, чтобы направитьзапрос post к правильной функции.

К сожалению, это не помогло с ошибкой.

Я что-то упустил?

views.py

class ConnectView(View):
    template_name = 'connect/home.html'
    def get(self, request, *args, **kwargs):
        f = ProfileFilter(request.GET, queryset=Profile.objects.exclude(user=request.user))
        context = {
            'users': User.objects.exclude(username=request.user),
            'friends': Friend.objects.filter(current_user=request.user),
            'filter': f,
        }
        return render(request, self.template_name, context)

    def post(self, request, *args, **kwargs):
        location = Location(latitude=request.POST['latitude'], longitude=request.POST['longitude'], user = request.user)
        location.save()
        if request.POST['radius']:
            radius_km = request.POST.get('radius', 0)
            queryset = User.objects.annotate(
                radius_sqr=pow(models.F('loc__latitude') -
                request.user.loc.latitude, 2) + pow(models.F('loc__longitude') -
                request.user.loc.longitude, 2)
                ).filter(
                radius_sqr__lte=pow(int(radius_km) / 9, 2)
                ).exclude(username=request.user)
            context = {'users': queryset}
        return JsonResponse({'message': 'success'})

home.html

<script>
  var pos;

  var $demo;

  function getLocation() {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(showPosition);
    } else {
      $demo.text("Geolocation is not supported by this browser.");
    }
  }

  function showPosition(position) {
    pos = position;
    var { latitude, longitude } = pos.coords;
    $('#btn_submit').attr("disabled", null);
  }

  $(document).ready(function() {
    $demo = $("#demo");
    $('#btn_submit').on('click', function() {
      var data = pos.coords;
      data.csrfmiddlewaretoken = $('input[name=csrfmiddlewaretoken]').val();
      $.post('', data, function() {
        alert("Location Confirmed!");
      });
    });
  });

</script>

      <h1>Connect with people.</h1>

            <!-- GET window.location IP Address / lat lon coordinates -->
            <p id="demo"></p>
            <button onclick="getLocation()" class="btn btn-warning" id="confirm">1. Find Location</button>
            <button type="submit" id="btn_submit" name="btn_submit"  class="btn btn-success" disabled>2. Submit Location </button>

            <!-- filter by profile attributes -->
            <form method="GET">
                {{ filter.form }}
                <button type="submit" class="small">Search.</button>
            </form>

            <!-- enter radius to filter by location-->
            <form method="POST">
              {% csrf_token %}
              <input type="number" name="radius">
              <input type="submit" value="filter by kilometers">
            </form>

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

В методе post вы добавили request.POST['latitude'], который вы не могли бы передать методом post.И ваше if.. состояние наступает после этого.Поэтому Django выдает ошибку, потому что он не находит ни одного параметра с этим именем и остановит дальнейшее выполнение.

Итак, при пост-запросе, если вы не передаете параметры широты и долготы, попробуйте записать его как:

request.POST.get('latitude', None)

или

поставьте условие if.. перед доступом к параметрам latitude и longitutde.

0 голосов
/ 15 февраля 2019

request.POST - это просто словарь Python (почти, он может иметь несколько значений для одного и того же ключа, отсюда и название класса MultiValueDict).Поэтому просто обработайте его как обычный объект словаря:

  • dict[key] поднимает KeyError, если key не существует
  • dict.get(key) возвращает значение для key или None, если он не существует.
  • dict.get(key, default) возвращает значение для key из default, если key не существует.

request.POST['latitude'], request.POST['longitude'] и request.POST['radius'] сгенерируют это исключение, если эти ключи не включены в параметры POST.Всегда используйте request.POST.get(param_name) при проверке того, что отправляется.

В вашем случае вы также должны добавить предложение if 'latitude' in request.POST and 'longitude' in request.POST, прежде чем делать что-либо с latitude и longitude.

...