# Sending location data from template JS to view

**URL:** <https://forum.djangoproject.com/t/sending-location-data-from-template-js-to-view/27275>\
**Category:** Templates & Frontend\
**Created:** [January 22, 2024, 8:41pm UTC](https://forum.djangoproject.com/t/sending-location-data-from-template-js-to-view/27275 "2024-01-22T20:41:38Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![DDave94](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/ddave94/32/18239_2.png) [@DDave94](https://forum.djangoproject.com/u/DDave94)\
**Post date:** [January 22, 2024, 8:41pm UTC](https://forum.djangoproject.com/t/sending-location-data-from-template-js-to-view/27275/1 "2024-01-22T20:41:39Z")

</div>

Hello,

I have a small problem in my simple application.

**Background**  
I have two views (home and search). On the home view, there is a search bar where the user types in a name of a service and the ‘search’ view is rendered. The search view (which requires a service name) then filters through my Shop model and finds all shops offering the service. In my home view template, I have the following JS script:

```auto
const findLoc = () => {
        var URL = "{% url 'home' %}"
        var django_csrf_token = '{{ csrf_token }}'
        const success = (position) => {
            const latitude = position.coords.latitude;
            const longitude = position.coords.longitude; 
            // console.log("longitude: " + longitude)
            // console.log("latitude: " + latitude)
            var data = {'latitude': latitude,
                        'longitude': longitude,
                        'csrfmiddlewaretoken': django_csrf_token };
            $.post(URL, data);
        }

        const error = () => {
            console.log('Location gathering Not allowed')
            const latitude = 43.6771296 // Default Latitude
            const longitude = -79.6333512 // Default Longtitude
            var data = {'latitude': latitude,
                        'longitude': longitude,
                        'csrfmiddlewaretoken': django_csrf_token };
            $.post(URL, data);
        }

        navigator.geolocation.getCurrentPosition(success,error);
    }
    // Location is fetched when user loads screen
    Window.onload = findLoc();
    // Location is fetched when user presses enter on home screen
    input_field = document.getElementById('service_name')
    input_field.addEventListener('keydown', (e) => {
      if (e.key =='Enter'){
        findLoc();
      }
    });
    // Location is fetched when user clicks on search button
    document.getElementById('searchButton').addEventListener('click', findLoc)

```

This script is basically sending user coordinates to the home view. In my search view, I have the coordinates of each shop and ultimately I want to display the distance from the user for each shop while rendering the search view, for this I will be using a Google API.

**Problem**

My problem is that the user longitude and latitude are extracted on the ‘home’ view and I don’t want to pass this information to the ‘search’ view via URL, because I don’t want to show this information in my URL path.

The other option I tried was to add the above JS on the ‘search’ view but I am not able to extract and post the user longitude and latitude like I did on the ‘home’ view.

```auto
def search(request, service_name):

    if request.method == 'POST': 
        user_lng = request.POST.get('longitude')
        user_lat = request.POST.get('latitude')
        print(user_lng, user_lat)
    else: 
        print('nothing')
    
    shops = Shop.objects.filter(services __name__ icontains = service_name).order_by("-created_on").distinct()

    return render(request, 'main/search.html', context = {
                                                          'searched':service_name,
                                                          'shops_found': shops})

```

**Is there a better way of doing this?** I know how to calculate the distance but I need to have the coordinates of the from location and to location in my search view so I can execute my downstream logic. (For each shop, I will save the distance which is a field of my shop model. Then I can re-filter the shops query set and order by distance and then send that to my search template.)

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 22, 2024, 8:49pm UTC](https://forum.djangoproject.com/t/sending-location-data-from-template-js-to-view/27275/2 "2024-01-22T20:49:47Z")

</div>

Is your jQuery post sending the data as JSON or as HTTP post data? (You can check this by seeing what’s being sent in the network tab of your browser’s developer tools.)

If it’s sending it as JSON, then you need to handle it as JSON in the view - which means reading it from `request.body` instead of `request.POST`. See [Request and response objects | Django documentation | Django](https://docs.djangoproject.com/en/5.0/ref/request-response/#django.http.HttpRequest.body).

For a situation such as this, you’re probably better off sending it as POST data.

Side note: Either way, I’d also suggest handling these data elements in a form. At a minimum, you could verify that they are reasonable and that the data hasn’t been inappropriately tampered with on the client to send bogus or malicious data. ( **Never** trust data submitted from the browser.)

---

<div class="post-metadata">

**Author:** ![DDave94](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/ddave94/32/18239_2.png) [@DDave94](https://forum.djangoproject.com/u/DDave94)\
**Post date:** [January 22, 2024, 9:10pm UTC](https://forum.djangoproject.com/t/sending-location-data-from-template-js-to-view/27275/3 "2024-01-22T21:10:50Z")

</div>

Thank you Ken!

Sorry I realized that I didn’t upload the JS script I am using on the ‘search’ template and I also didn’t import the JQuery Script. I’m new to JS development so I didn’t know that the “$.post” is a JQuery thing. Here is my script now and it is working, I am able to get the user’s location when the search page loads and I am sending POST data because in my ‘search’ view I can extract the data using request.post.get

```auto
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
    
    <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
    
    <script>
        const findLoc = () => {
            var URL = "{% url 'search' searched %}"
            var django_csrf_token = '{{ csrf_token }}'
            const success = (position) => {
                const latitude = position.coords.latitude;
                const longitude = position.coords.longitude; 
                var data = {'latitude': latitude,
                            'longitude': longitude,
                            'csrfmiddlewaretoken': django_csrf_token };
                $.post(URL, data);
            }
    
            const error = () => {
                console.log('Location gathering Not allowed')
                const latitude = 43.6771296 // Default Latitude
                const longitude = -79.6333512 // Default Longtitude
                var data = {'latitude': latitude,
                            'longitude': longitude,
                            'csrfmiddlewaretoken': django_csrf_token };
                $.post(URL, data);
            }
    
            navigator.geolocation.getCurrentPosition(success,error);
        }
        // Location is fetched when user loads screen
        Window.onload = findLoc();
      </script>

```

Because I am getting the location on Window Load, I am thinking of asking the user to provide their location on the homepage to avoid having to reload the page if they allow location access on the search page.

> [@KenWhitesell](#):
>
> Side note: Either way, I’d also suggest handling these data elements in a form. At a minimum, you could verify that they are reasonable and that the data hasn’t been inappropriately tampered with on the client to send bogus or malicious data. ( **Never** trust data submitted from the browser.)

**Two Questions**

1. In regards to what you said here, to achieve this I can create a form using the longitude and latitude within my JS script and then submit that form via JS right? Can you please provide an example of this if you have anything.

2. Also, from a high level perspective, is my method of using the user location and calculating distances within the search view to show nearby shops first an efficient way of achieving what I want. I’m just thinking if there are 100-200 shops in the future, and I have to calculate the distance for each, it will be alot of API calls and alot of computation. Unfortunately, I don’t think I can save this data for each user that visits my website, but maybe I can do this for users who are authenticated?

Thank you so much!

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 22, 2024, 9:53pm UTC](https://forum.djangoproject.com/t/sending-location-data-from-template-js-to-view/27275/4 "2024-01-22T21:53:37Z")

</div>

> [@DDave94](#):
>
> In regards to what you said here, to achieve this I can create a form using the longitude and latitude within my JS script and then submit that form via JS right? Can you please provide an example of this if you have anything.

You don’t need to do it that way.

Keep in mind that a “Django Form” is a Python object that exists in the server. One of its functions is to create an HTML representation of that object. However, a Django Form is _not_ HTML. There is nothing within a Django Form that _requires_ any HTML be associated with it.

You can create the form, and bind the post data to it, without ever having generated any HTML.

When you create an instance of a form class with data that has been submitted, it’s known as “binding” data to the form. In the general case, it’s most frequently used with POST data that has been submitted.

However, `request.POST` is a type of dict. What’s _really_ happening is that the dict is the data being bound to the forms. And the dict that you use doesn’t need to be retrieved from `request.POST`. You can bind _any_ dict to a form - including JSON submitted via AJAX and deserialized.

See the docs for [Bound and unbound forms](https://docs.djangoproject.com/en/5.0/ref/forms/api/#bound-and-unbound-forms) for an example.

> [@DDave94](#):
>
> I’m just thinking if there are 100-200 shops in the future, and I have to calculate the distance for each, it will be alot of API calls and alot of computation.

That’s one of the purposes and features of the GIS-related functions in GeoDjango (e.g., PostGIS for PostgreSQL). See [GeoDjango | Django documentation | Django](https://docs.djangoproject.com/en/5.0/ref/contrib/gis/)  
(Also, skip ahead and see [GeoDjango Database API | Django documentation | Django](https://docs.djangoproject.com/en/5.0/ref/contrib/gis/db-api/) to get some idea of what’s immediately available to you.)

Depending upon the number of users and the number of shops, you _could_ create a many-to-many relationship with a through model containing the distance between the two.

---

<div class="post-metadata">

**Author:** ![DDave94](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/ddave94/32/18239_2.png) [@DDave94](https://forum.djangoproject.com/u/DDave94)\
**Post date:** [January 22, 2024, 10:32pm UTC](https://forum.djangoproject.com/t/sending-location-data-from-template-js-to-view/27275/5 "2024-01-22T22:32:18Z")

</div>

> [@KenWhitesell](#):
>
> See the docs for [Bound and unbound forms](https://docs.djangoproject.com/en/5.0/ref/forms/api/#bound-and-unbound-forms) for an example.

So based on what I’m reading here, I would create a Form in forms.py for holding the latitude and longitude coordinates. Then in my ‘search’ view, when I read the POST dict returned template, I would instantiate the form and then do a form.is\_valid() to make sure I didn’t get any malicious or incorrect data right?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 22, 2024, 10:46pm UTC](https://forum.djangoproject.com/t/sending-location-data-from-template-js-to-view/27275/6 "2024-01-22T22:46:32Z")

</div>

Yep, that’s it. After that, your view can process those values anyway you want.
