Reputation: 771
I'm trying to have all location functionality on one page, such as
get users location
, post it to the database
, then filter results
based on a user-inputted kilometre radius value.
I am getting MultiValueDictKeyError at /connect/ 'latitude'
because the POST request is going to
location = Location(latitude=request.POST['latitude'], longitude=request.POST['longitude'], user = request.user)
when it should be going to
if request.POST['radius']:
radius_km = request.POST.get('radius', 0)
I researched how to stop this happening and saw I could do if request.POST['radius']:
to direct the post request to the right function.
This hasn't helped with the error unfortunately.
Am I missing something?
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>
Upvotes: 0
Views: 150
Reputation: 20702
request.POST
is just a python dictionary (almost, it can have multiple values for the same key, hence the class name MultiValueDict
). So just treat it as a normal dictionary object:
dict[key]
raises a KeyError
if the key
doesn't existdict.get(key)
returns the value for key
or None
if it doesn't exist.dict.get(key, default)
returns the value for key
of default
if the key
doesn't exist.request.POST['latitude']
, request.POST['longitude']
and request.POST['radius']
will throw this exception if these keys aren't in the POST parameters. Always use request.POST.get(param_name)
when checking what is being submitted.
In your case, you should also add an if 'latitude' in request.POST and 'longitude' in request.POST
clause before doing anything with latitude
and longitude
.
Upvotes: 1
Reputation: 1340
In your post method, you have added request.POST['latitude']
, which you might not be passing with the post method. And your if..
condition comes after that. Therefore Django gives you error, because it doesn't find any parameter with this name, and will stop the further execution.
So, on post request if you are not passing latitude longitude parameters try writting it as:
request.POST.get('latitude', None)
or,
put your if..
condition before accessing latitude
and longitutde
parameters.
Upvotes: 2