How to do it...

Go through the following steps:

  1. Register for the Google Maps API key. You can learn how and where to do this at the Google developers' documentation at https://developers.google.com/maps/documentation/javascript/get-api-key.
  1. Add the Google Maps API key to the secrets and then read it out in the settings:
# myproject/settings/_base.py
# …
GOOGLE_MAPS_API_KEY = get_secret("GOOGLE_MAPS_API_KEY")
  1. At the core app, create a context processor to expose GOOGLE_MAPS_API_KEY to the templates:
# myproject/apps/core/context_processors.py
from django.conf import settings

def google_maps(request):
return {
"GOOGLE_MAPS_API_KEY": settings.GOOGLE_MAPS_API_KEY,
}
  1. Refer to this context processor in the template settings:
# myproject/settings/_base.py
TEMPLATES = [
{
"BACKEND":
"django.template.backends.django.DjangoTemplates",
"DIRS": [os.path.join(BASE_DIR, "myproject", "templates")],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors
.messages"
,
"django.template.context_processors.media",
"django.template.context_processors.static",
"sekizai.context_processors.sekizai",
"myproject.apps.core.context_processors
.google_maps"
,

]
},
}
]
  1. Create the list and detail views for the locations:
# myproject/apps/locations/views.py
from django.views.generic import ListView, DetailView
from .models import Location

class LocationList(ListView):
model = Location
paginate_by = 10

class LocationDetail(DetailView):
model = Location
context_object_name = "location"
  1. Create the URL configuration for the locations app:
# myproject/apps/locations/urls.py
from django.urls import path
from .views import LocationList, LocationDetail

urlpatterns = [
path("", LocationList.as_view(), name="location_list"),
path("<uuid:pk>/", LocationDetail.as_view(),
name="location_detail"),
]
  1. Include the URLs of the locations in the project's URL configuration:
# myproject/urls.py
from django.contrib import admin
from django.conf.urls.i18n import i18n_patterns
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static
from django.shortcuts import redirect

from myproject.apps.core import views as core_views


urlpatterns = i18n_patterns(
path("", lambda request: redirect("locations:location_list")),
path("admin/", admin.site.urls),
path("accounts/", include("django.contrib.auth.urls")),
path("locations/", include(("myproject.apps.locations.urls",
"locations"), namespace="locations")),

path("js-settings/", core_views.js_settings,
name="js_settings"),
)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static("/media/", document_root=settings.MEDIA_ROOT)
  1. It is time to create the template for the location list and location detail views. The location list will be as simple as possible for now; we only need it to be able to browse the locations and get to the location detail views.
{# locations/location_list.html #}
{% extends "base.html" %}
{% load i18n %}

{% block content %}
<h1>{% trans "Interesting Locations" %}</h1>
{% if object_list %}
<ul>
{% for location in object_list %}
<li><a href="{{ location.get_url_path }}">
{{ location.name }}

</a></li>
{% endfor %}
</ul>
{% else %}
<p>{% trans "There are no locations yet." %}</p>
{% endif %}
{% endblock %}
  1. Next, let's create a template for the location details by extending the base.html and overwriting the content block:
{# locations/location_detail.html #}
{% extends "base.html" %}
{% load i18n static %}

{% block content %}
<a href="{% url "locations:location_list" %}">{% trans
"Interesting Locations" %}</a>
<h1 class="map-title">{{ location.name }}</h1>
<div class="my-3">
{{ location.description|linebreaks|urlize }}
</div>
{% with geoposition=location.get_geoposition %}
<div id="map" class="mb-3"
data-latitude="{{ geoposition.latitude|stringformat:"f" }}"
data-longitude="{{ geoposition.longitude|stringformat:"f" }}"
data-address="{{ location.get_full_address }}"></div>

{% endwith %}
{% endblock %}
  1. Also in the same template, overwrite the js block:
{% block js %}
<script src="{% static 'site/js/location_detail.js' %}"></script>
<script async defer src="https://maps-api-
ssl.google.com/maps/api/js?key=
{{ GOOGLE_MAPS_API_KEY }}&callback=Location.init"></script>
{% endblock %}
  1. As well as the templates, we need the JavaScript file that will read out the HTML5 data attributes and use them to render a map with a marker on it:
/* site_static/site/js/location_detail.js */
(function(window) {
"use strict";

function Location() {
this.case = document.getElementById("map");
if (this.case) {
this.getCoordinates();
this.getAddress();
this.getMap();
this.getMarker();
this.getInfoWindow();
}
}

Location.prototype.getCoordinates = function() {
this.coords = {
lat: parseFloat(this.case.getAttribute("data-
latitude"
)),
lng: parseFloat(this.case.getAttribute("data-
longitude"
))
};
};

Location.prototype.getAddress = function() {
this.address = this.case.getAttribute("data-address");
};

Location.prototype.getMap = function() {
this.map = new google.maps.Map(this.case, {
zoom: 15,
center: this.coords
});
};

Location.prototype.getMarker = function() {
this.marker = new google.maps.Marker({
position: this.coords,
map: this.map
});
};

Location.prototype.getInfoWindow = function() {
var self = this;
var wrap = this.case.parentNode;
var title = wrap.querySelector(".map-title").textContent;

this.infoWindow = new google.maps.InfoWindow({
content: "<h3>"+title+"</h3><p>"+this.address+"</p>"
});

this.marker.addListener("click", function() {
self.infoWindow.open(self.map, self.marker);
});
};

var instance;
Location.init = function() {
// called by Google Maps service automatically once loaded
// but is designed so that Location is a singleton
if (!instance) {
instance = new Location();
}
};

// expose in the global namespace
window.Location = Location;
}(window));
  1. For the map to be displayed nicely, we need to set some CSS, as shown in the following code:
/* site_static/site/css/style.css */
#map {
box-sizing: padding-box;
height: 0;
padding-bottom: calc(9 / 16 * 100%); /* 16:9 aspect ratio */
width: 100%;
}
@media screen and (max-width: 480px) {
#map {
display: none; /* hide on mobile devices (esp. portrait) */
}
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.161.222