Google Maps Not Rendering Using Django Easy Maps

Building interactive maps into a Django web application can seem daunting if you do not know where to begin, but it is easier than you think if you use a developer tool such as Mapbox.

In this post we will build a simple Django project with a single app and add an interactive map like the one you see below to the webpage that Django renders with the Mapbox Maps API.

Our Tools

Python 3 is strongly recommended for this tutorial because Python 2 will no longer be supported starting January 1, 2020. Python 3.6.5 to was used to build this tutorial. We will also use the following application dependencies to build our application:

  • Django web framework, version 2.0.5
  • pip and virtualenv, which come installed with Python 3, to install and isolate the Django library from your other applications
  • A free Mapbox account to interact with their web API using JavaScript

If you need help getting your development environment configured before running this code, take a look at this guide for setting up Python 3 and Django on Ubuntu 16.04 LTS.

This blog post's code is also available on GitHub within the maps-django-mapbox directory of the blog-code-examples repository. Take the code and use it for your own purposes because it is all provided under the MIT open source license.

Installing Dependencies

Start the Django project by creating a new virtual environment using the following command. I recommend using a separate directory such as ~/venvs/ (the tilde is a shortcut for your user's home directory) so that you always know where all your virtualenvs are located.

            python3 -m venv djangomaps          

Activate the virtualenv with the activate shell script:

            source djangomaps/bin/activate          

The command prompt will change after activating the virtualenv:

Activate your djangomaps virtualenv.

Remember that you have to activate your virtualenv in every new terminal window where you want to use dependencies in the virtualenv.

We can now install the Django package into the activated but otherwise empty virtualenv.

            pip install django==2.0.5          

Look for the following output to confirm Django installed correctly from PyPI.

                        Downloading https://files.pythonhosted.org/packages/23/91/2245462e57798e9251de87c88b2b8f996d10ddcb68206a8a020561ef7bd3/Django-2.0.5-py3-none-any.whl (7.1MB)       100% |████████████████████████████████|            7.1MB 231kB/s        Collecting pytz (from django==2.0.5)         Using cached https://files.pythonhosted.org/packages/dc/83/15f7833b70d3e067ca91467ca245bae0f6fe56ddc7451aa0dc5606b120f2/pytz-2018.4-py2.py3-none-any.whl         Installing collected packages: pytz, django         Successfully installed django-2.0.5 pytz-2018.4          

The Django dependency is ready to go so now we can create our project and add some awesome maps to the application.

Building Our Django Project

We can use the Django django-admin.py tool to create the boilerplate code structure to get our project started. Change into the directory where you develop your applications. For example, I typically use /Users/matt/devel/py/. Then run the following command to start a Django project named djmaps:

            django-admin.py startproject djmaps          

The django-admin.py command will create a directory named djmaps along with several subdirectories that you should be familiar with if you have previously worked with Django.

Change directories into the new project.

Create a new Django app within djmaps.

            python manage.py startapp maps          

Django will generate a new folder named maps for the project. We should update the URLs so the app is accessible before we write our views.py code.

Open djmaps/djmaps/urls.py. Add the highlighted lines so that URLs will check the maps app for appropriate URL matching.

            """ (comments) """            from django.conf.urls import include            from django.contrib import admin from django.urls import path   urlpatterns = [                          path('', include('maps.urls')),            path('admin/', admin.site.urls), ]          

Save djmaps/djmaps/urls.py and open djmaps/djmaps/settings.py. Add the maps app to settings.py by inserting the highlighted line:

            # Application definition  INSTALLED_APPS = [      'django.contrib.admin',     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.messages',     'django.contrib.staticfiles',                          'maps',            ]          

Make sure you change the default DEBUG and SECRET_KEY values in settings.py before you deploy any code to production. Secure your app properly with the information from the Django production deployment checklist so that you do not add your project to the list of hacked applications on the web.

Save and close settings.py.

Next change into the djmaps/maps directory. Create a new file named urls.py to contain routes for the maps app.

Add these lines to the empty djmaps/maps/urls.py file.

            from django.conf.urls import url                                                                                                                               from . import views  urlpatterns = [      url(r'', views.default_map, name="default"), ]          

Save djmaps/maps/urls.py and open djmaps/maps/views.py add the following two highlighted lines. You can keep the boilerplate comment or delete it.

            from django.shortcuts import render            def default_map(request):                          return render(request, 'default.html', {})          

Next, create a directory for your template files named templates under the djmaps/maps app directory.

Create a new file named default.html within djmaps/maps/templates that contains the following Django template markup.

                        <!DOCTYPE html>            <html>   <head>     <title>Interactive maps for Django web apps</title>            </head>   <body>    <h1>Map time!</h1>            </body>            </html>          

We can test out this static page to make sure all of our code is correct, then we'll use Mapbox to embed a customizable map within the page. Change into the base directory of your Django project where the manage.py file is located. Execute the development server with the following command:

            python manage.py runserver          

The Django development server will start up with no issues other than an unapplied migrations warning.

                        Performing            system            checks...            System            check            identified            no            issues            (0            silenced            ).            You            have            14            unapplied            migration            (            s            ).            Your            project            may            not            work            properly            until            you            apply            the            migrations            for            app            (            s            ):            admin,            auth,            contenttypes,            sessions.            Run            'python manage.py migrate'            to            apply            them.            May            21, 2018 - 12:47:54            Django            version            2.0.5,            using            settings            'djmaps.settings'            Starting            development            server            at            http://127.0.0.1:8000/            Quit            the            server            with            CONTROL-C.          

Open a web browser and go to localhost:8000.

Plain old HTML page.

Our code works, but boy is that a plain-looking HTML page. Let's make the magic happen by adding JavaScript to the template to generate maps.

Adding Maps with Mapbox

Head to mapbox.com in your web browser to access the Mapbox homepage.

Mapbox homepage.

Click on "Get Started" or "Get Started for free" (the text depends on whether or not you already have a Mapbox account).

Sign up for a Mapbox account.

Sign up for a new free developer account or sign in to your existing account.

Add Mapbox to your application.

Click the "JS Web" option.

Choose the method of installation.

Choose "Use the Mapbox CDN" for the installation method. The next two screens show some code that you should add to your djmaps/maps/templates/default.html template file. The code will look like the following but you will need to replace the mapboxgl.accessToken line with your own access token.

                        <!DOCTYPE html>            <html>   <head>     <title>Interactive maps for Django web apps</title>                          <script              src='https://api.mapbox.com/mapbox-gl-js/v0.44.2/mapbox-gl.js'              ></script>                          <link              href='https://api.mapbox.com/mapbox-gl-js/v0.44.2/mapbox-gl.css'              rel='stylesheet'              />            </head>   <body>    <h1>Map time!</h1>                          <div              id='map'              width="100%"              style='height:400px'              ></div>                          <script>                          mapboxgl.accessToken              =              {{              mapbox_access_token              }};                          var              map              = new              mapboxgl.Map({                          container: 'map',                          style: 'mapbox://styles/mapbox/streets-v10'                          });                          </script>            </body>            </html>          

Re-open djmaps/maps/views.py to update the parameters passed into the Django template.

            from django.shortcuts import render   def default_map(request):                          # TODO: move this token to Django settings from an environment variable                          # found in the Mapbox account settings and getting started instructions                          # see https://www.mapbox.com/account/ under the "Access tokens" section                          mapbox_access_token = 'pk.my_mapbox_access_token'                          return render(request, 'default.html',                                      { 'mapbox_access_token': mapbox_access_token })          

The Mapbox access token should really be stored in the Django settings file, so we left a "TODO" note to handle that as a future step.

Now we can try our webpage again. Refresh localhost:8000 in your web browser.

Screenshot of the Mapbox map showing up in our Django front end.

Sweet, we've got a live, interactive map! It's kind of weird thought how it is zoomed out to view the entire world. Time to customize the map using a few JavaScript parameters.

Customizing the Map

We can modify the map by changing parameters for the style, zoom level, location and many other attributes.

We'll start by changing the location that the initial map centers in on as well as the zoom level.

Re-open djmaps/maps/templates/default.html and modify the first highlighted lines so it ends with a commas and add the two new highlighted lines shown below.

                        <!DOCTYPE html>            <html>   <head>     <title>Interactive maps for Django web apps</title>     <script            src='https://api.mapbox.com/mapbox-gl-js/v0.44.2/mapbox-gl.js'            ></script>     <link            href='https://api.mapbox.com/mapbox-gl-js/v0.44.2/mapbox-gl.css'            rel='stylesheet'            />            </head>   <body>    <h1>Map time!</h1>    <div            id='map'            width="100%"            style='height:400px'            ></div>    <script>            mapboxgl.accessToken            =            {{            mapbox_access_token            }};            var            map            = new            mapboxgl.Map({            container: 'map',                          style: 'mapbox://styles/mapbox/streets-v10',                          center: [-77.03,              38.91],                          zoom:              9                        });            </script>            </body>            </html>          

The first number, -77.03, for the center array is the longitude and the second number, 38.91, is the latitude. Zoom level 9 is much closer to the city than the default which was the entire world at level 0. All of the customization values are listed in the Mapbox GL JS API documentation.

Now refresh the page at localhost:8000 to reload our map.

Updated map centered and zoomed in on Washington, D.C.

Awesome, now we are zoomed in on Washington, D.C. and can still move around to see more of the map. Let's make a couple other changes to our map before wrapping up.

Again back in djmaps/maps/templates/default.html change the highlighted line for the style key to the mapbox://styles/mapbox/satellite-streets-v10 value. That will change the look from an abstract map style to satellite image data. Update zoom: 9 so that it has a comma at the end of the line and add bearing: 180 as the last key-value pair in the configuration.

                        <!DOCTYPE html>            <html>   <head>     <title>Interactive maps for Django web apps</title>     <script            src='https://api.mapbox.com/mapbox-gl-js/v0.44.2/mapbox-gl.js'            ></script>     <link            href='https://api.mapbox.com/mapbox-gl-js/v0.44.2/mapbox-gl.css'            rel='stylesheet'            />            </head>   <body>    <h1>Map time!</h1>    <div            id='map'            width="100%"            style='height:400px'            ></div>    <script>            mapboxgl.accessToken            =            {{            mapbox_access_token            }};            var            map            = new            mapboxgl.Map({            container: 'map',                          style: 'mapbox://styles/mapbox/satellite-streets-v10',                          center: [-77.03,              38.91],                          zoom:              9,                          bearing:              180                        });            </script>            </body>            </html>          

Save the template and refresh localhost:8000.

Updated map with satellite imagery and street map overlay.

The map now provides a satellite view with streets overlay but it is also... "upside down"! At least the map is upside down compared to how most maps are drawn, due to the bearing: 180 value, which modified this map's rotation.

Not bad for a few lines of JavaScript in our Django application. Remember to check the Mapbox GL JS API documentation for the exhaustive list of parameters that you can adjust.

What's Next?

We just learned how to add interactive JavaScript-based maps to our Django web applications, as well as modify the look and feel of the maps. Next try out some of the other APIs Mapbox provides including:

  • directions
  • map matching
  • geocoding

Questions? Let me know via a GitHub issue ticket on the Full Stack Python repository, on Twitter @fullstackpython or @mattmakai.

Do you see a typo, syntax issue or wording that's confusing in this blog post? Fork this page's source on GitHub and submit a pull request with a fix or file an issue ticket on GitHub.

vancelantoo.blogspot.com

Source: https://www.fullstackpython.com/blog/maps-django-web-applications-projects-mapbox.html

0 Response to "Google Maps Not Rendering Using Django Easy Maps"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel