├── .gitignore
├── README.md
├── db.sqlite3
├── did_django_google_waypoints
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-37.pyc
│ ├── settings.cpython-37.pyc
│ ├── urls.cpython-37.pyc
│ └── wsgi.cpython-37.pyc
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
├── main
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-37.pyc
│ ├── admin.cpython-37.pyc
│ ├── apps.cpython-37.pyc
│ ├── mixins.cpython-37.pyc
│ ├── models.cpython-37.pyc
│ ├── urls.cpython-37.pyc
│ └── views.cpython-37.pyc
├── admin.py
├── apps.py
├── migrations
│ ├── __init__.py
│ └── __pycache__
│ │ └── __init__.cpython-37.pyc
├── mixins.py
├── models.py
├── templates
│ └── main
│ │ ├── base.html
│ │ ├── map.html
│ │ ├── partials
│ │ └── logo.html
│ │ └── route.html
├── tests.py
├── urls.py
└── views.py
├── manage.py
├── requirements.txt
└── static
├── branding
├── did-logo.gif
├── did_logo.gif
├── did_logo.jpg
├── did_logo.mp4
└── did_logo.png
├── google_maps.js
├── google_places.js
├── main.css
└── main.js
/.gitignore:
--------------------------------------------------------------------------------
1 | settings.ini
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # did_django_google_waypoints
2 | Django project that uses Googles APIs to auto populate fields, display maps and routes for multiple waypoints
3 |
4 | 1) cd to development directory
5 | 2) mkvirtualenv did_django_google_maps_api
6 | 3) mkdir did_django_google_maps_api
7 | 4) clone repository to new directory
8 | 5) pip install -r requirements.txt
9 | 6) Create and update settings.ini with your email API information
10 |
11 | API_KEY = "XXX"
12 |
13 |
14 | 7) python manage.py makemigrations
15 | 8) python manage.py migrate
16 | 9) python manage.py runserver
17 | 10) https://localhost:8000 - Bob's your uncle!!
18 |
19 | Note:
20 |
21 | Don't forget to activate the following Google API's
22 |
23 | Places API
24 | Maps Javascript API
25 | Directions API
26 | Distance Matrix API
27 | Geocoding API
28 |
29 |
30 |
--------------------------------------------------------------------------------
/db.sqlite3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/db.sqlite3
--------------------------------------------------------------------------------
/did_django_google_waypoints/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/did_django_google_waypoints/__init__.py
--------------------------------------------------------------------------------
/did_django_google_waypoints/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/did_django_google_waypoints/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/did_django_google_waypoints/__pycache__/settings.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/did_django_google_waypoints/__pycache__/settings.cpython-37.pyc
--------------------------------------------------------------------------------
/did_django_google_waypoints/__pycache__/urls.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/did_django_google_waypoints/__pycache__/urls.cpython-37.pyc
--------------------------------------------------------------------------------
/did_django_google_waypoints/__pycache__/wsgi.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/did_django_google_waypoints/__pycache__/wsgi.cpython-37.pyc
--------------------------------------------------------------------------------
/did_django_google_waypoints/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for did_django_google_waypoints project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'did_django_google_waypoints.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/did_django_google_waypoints/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for did_django_google_waypoints project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.2.2.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.2/ref/settings/
11 | """
12 |
13 | from pathlib import Path
14 | import os
15 | from decouple import config
16 |
17 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
18 | BASE_DIR = Path(__file__).resolve().parent.parent
19 |
20 |
21 | # Quick-start development settings - unsuitable for production
22 | # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
23 |
24 | # SECURITY WARNING: keep the secret key used in production secret!
25 | SECRET_KEY = 'django-insecure-76-s$==ou!m4&tyq#mv0i2@n&*o)))-uw-ckquz%j*vg48()n7'
26 |
27 | # SECURITY WARNING: don't run with debug turned on in production!
28 | DEBUG = True
29 |
30 | ALLOWED_HOSTS = []
31 |
32 |
33 | # Application definition
34 |
35 | INSTALLED_APPS = [
36 | 'django.contrib.admin',
37 | 'django.contrib.auth',
38 | 'django.contrib.contenttypes',
39 | 'django.contrib.sessions',
40 | 'django.contrib.messages',
41 | 'django.contrib.staticfiles',
42 | 'main'
43 | ]
44 |
45 | MIDDLEWARE = [
46 | 'django.middleware.security.SecurityMiddleware',
47 | 'django.contrib.sessions.middleware.SessionMiddleware',
48 | 'django.middleware.common.CommonMiddleware',
49 | 'django.middleware.csrf.CsrfViewMiddleware',
50 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
51 | 'django.contrib.messages.middleware.MessageMiddleware',
52 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
53 | ]
54 |
55 | ROOT_URLCONF = 'did_django_google_waypoints.urls'
56 |
57 | TEMPLATES = [
58 | {
59 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
60 | 'DIRS': [],
61 | 'APP_DIRS': True,
62 | 'OPTIONS': {
63 | 'context_processors': [
64 | 'django.template.context_processors.debug',
65 | 'django.template.context_processors.request',
66 | 'django.contrib.auth.context_processors.auth',
67 | 'django.contrib.messages.context_processors.messages',
68 | ],
69 | },
70 | },
71 | ]
72 |
73 | WSGI_APPLICATION = 'did_django_google_waypoints.wsgi.application'
74 |
75 |
76 | # Database
77 | # https://docs.djangoproject.com/en/3.2/ref/settings/#databases
78 |
79 | DATABASES = {
80 | 'default': {
81 | 'ENGINE': 'django.db.backends.sqlite3',
82 | 'NAME': BASE_DIR / 'db.sqlite3',
83 | }
84 | }
85 |
86 |
87 | # Password validation
88 | # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
89 |
90 | AUTH_PASSWORD_VALIDATORS = [
91 | {
92 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
93 | },
94 | {
95 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
96 | },
97 | {
98 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
99 | },
100 | {
101 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
102 | },
103 | ]
104 |
105 |
106 | # Internationalization
107 | # https://docs.djangoproject.com/en/3.2/topics/i18n/
108 |
109 | LANGUAGE_CODE = 'en-gb'
110 |
111 | TIME_ZONE = 'UTC'
112 |
113 | USE_I18N = True
114 |
115 | USE_L10N = True
116 |
117 | USE_TZ = True
118 |
119 |
120 | # Static files (CSS, JavaScript, Images)
121 | # https://docs.djangoproject.com/en/3.2/howto/static-files/
122 | STATICFILES_DIRS = [
123 | os.path.join(BASE_DIR, "static")
124 | ]
125 | STATIC_URL = '/static/'
126 | STATIC_ROOT = os.path.join(BASE_DIR, "static_cdn")
127 |
128 | # Default primary key field type
129 | # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
130 |
131 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
132 |
133 | API_KEY = config("API_KEY")
134 |
--------------------------------------------------------------------------------
/did_django_google_waypoints/urls.py:
--------------------------------------------------------------------------------
1 | """did_django_google_waypoints URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import path, include
18 | from django.conf import settings
19 | from django.conf.urls.static import static
20 |
21 |
22 | urlpatterns = [
23 | path('', include('main.urls', namespace="main")),
24 | path('admin/', admin.site.urls),
25 | ]
26 |
27 | if settings.DEBUG:
28 | urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
--------------------------------------------------------------------------------
/did_django_google_waypoints/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for did_django_google_waypoints project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'did_django_google_waypoints.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/main/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/main/__init__.py
--------------------------------------------------------------------------------
/main/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/main/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/main/__pycache__/admin.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/main/__pycache__/admin.cpython-37.pyc
--------------------------------------------------------------------------------
/main/__pycache__/apps.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/main/__pycache__/apps.cpython-37.pyc
--------------------------------------------------------------------------------
/main/__pycache__/mixins.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/main/__pycache__/mixins.cpython-37.pyc
--------------------------------------------------------------------------------
/main/__pycache__/models.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/main/__pycache__/models.cpython-37.pyc
--------------------------------------------------------------------------------
/main/__pycache__/urls.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/main/__pycache__/urls.cpython-37.pyc
--------------------------------------------------------------------------------
/main/__pycache__/views.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/main/__pycache__/views.cpython-37.pyc
--------------------------------------------------------------------------------
/main/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/main/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class MainConfig(AppConfig):
5 | default_auto_field = 'django.db.models.BigAutoField'
6 | name = 'main'
7 |
--------------------------------------------------------------------------------
/main/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/main/migrations/__init__.py
--------------------------------------------------------------------------------
/main/migrations/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/main/migrations/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/main/mixins.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | import requests
3 | import json
4 | import datetime
5 | from humanfriendly import format_timespan
6 |
7 |
8 | '''
9 | Handles directions from Google
10 | '''
11 | def Directions(*args, **kwargs):
12 |
13 | lat_a = kwargs.get("lat_a")
14 | long_a = kwargs.get("long_a")
15 | lat_b = kwargs.get("lat_b")
16 | long_b = kwargs.get("long_b")
17 | lat_c = kwargs.get("lat_c")
18 | long_c = kwargs.get("long_c")
19 | lat_d = kwargs.get("lat_d")
20 | long_d = kwargs.get("long_d")
21 |
22 | origin = f'{lat_a},{long_a}'
23 | destination = f'{lat_b},{long_b}'
24 | waypoints = f'{lat_c},{long_c}|{lat_d},{long_d}'
25 |
26 | result = requests.get(
27 | 'https://maps.googleapis.com/maps/api/directions/json?',
28 | params={
29 | 'origin': origin,
30 | 'destination': destination,
31 | 'waypoints': waypoints,
32 | "key": settings.API_KEY
33 | })
34 |
35 | directions = result.json()
36 |
37 | if directions["status"] == "OK":
38 |
39 | routes = directions["routes"][0]["legs"]
40 |
41 |
42 | distance = 0
43 | duration = 0
44 | route_list = []
45 |
46 | for route in range(len(routes)):
47 |
48 | distance += int(routes[route]["distance"]["value"])
49 | duration += int(routes[route]["duration"]["value"])
50 |
51 | route_step = {
52 | 'origin': routes[route]["start_address"],
53 | 'destination': routes[route]["end_address"],
54 | 'distance': routes[route]["distance"]["text"],
55 | 'duration': routes[route]["duration"]["text"],
56 |
57 | 'steps': [
58 | [
59 | s["distance"]["text"],
60 | s["duration"]["text"],
61 | s["html_instructions"],
62 |
63 | ]
64 | for s in routes[route]["steps"]]
65 | }
66 |
67 |
68 | route_list.append(route_step)
69 |
70 |
71 | return {
72 | "origin": origin,
73 | "destination": destination,
74 | "distance": f"{round(distance/1000, 2)} Km",
75 | "duration": format_timespan(duration),
76 | "route": route_list
77 | }
--------------------------------------------------------------------------------
/main/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/main/templates/main/base.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {% block extend_head %}
15 |
16 | {% endblock %}
17 |
18 |
19 |
20 |
21 |
22 | {% block extend_nav %}
23 |
24 | {% endblock %}
25 |
26 |
27 |
28 | {% include 'main/partials/logo.html' %}
29 |
30 | {% block content %}
31 |
32 | {% endblock %}
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | {% block extend_footer %}
41 |
42 | {% endblock %}
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/main/templates/main/map.html:
--------------------------------------------------------------------------------
1 | {% extends 'main/base.html' %}
2 | {% load static %}
3 |
4 |
5 | {% block extend_head %}
6 |
7 |
8 |
9 |
10 |
11 | {% endblock %}
12 |
13 | {% block extend_nav %}
14 |
15 |
19 |
20 | {% endblock %}
21 |
22 |
23 | {% block content %}
24 |
25 | Django Google Maps Waypoints API Demo - Map
26 |
27 |
28 |
29 |
30 |
31 |
32 | Field |
33 | |
34 |
35 |
36 |
37 |
38 | Start |
39 | {{directions.origin}} |
40 |
41 |
42 | Destination |
43 | {{directions.destination}} |
44 |
45 |
46 | Duration |
47 | {{directions.duration}} |
48 |
49 |
50 | Distance |
51 | {{directions.distance}} |
52 |
53 |
54 | Directions |
55 | click here |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | Directions |
65 | Distance |
66 | Duration |
67 |
68 |
69 |
70 | {% for leg in directions.route %}
71 |
72 | Leg {{ forloop.counter }} |
73 | |
74 | |
75 |
76 | {% for dist, dur, text in leg.steps %}
77 |
78 | {{text|safe}} |
79 | {{dist}} |
80 | {{dur}} |
81 |
82 | {% endfor %}
83 | {% endfor %}
84 |
85 |
86 |
87 |
88 |
89 |
95 |
96 | {% endblock %}
97 |
98 | {% block extend_footer %}
99 |
100 |
101 |
117 |
118 |
119 |
120 |
121 | {% endblock %}
--------------------------------------------------------------------------------
/main/templates/main/partials/logo.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 |

5 |
6 |
--------------------------------------------------------------------------------
/main/templates/main/route.html:
--------------------------------------------------------------------------------
1 | {% extends 'main/base.html' %}
2 | {% load static %}
3 |
4 |
5 | {% block extend_head %}
6 |
7 |
8 |
9 | {% endblock %}
10 |
11 | {% block extend_nav %}
12 |
13 |
17 |
18 | {% endblock %}
19 |
20 |
21 | {% block content %}
22 |
23 | Django Google Maps Waypoints API Demo - Routing
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | {% endblock %}
55 |
56 | {% block extend_footer %}
57 |
58 |
59 |
64 |
65 |
66 |
67 |
68 | {% endblock %}
--------------------------------------------------------------------------------
/main/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/main/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from . import views
3 |
4 | app_name = "main"
5 |
6 |
7 | urlpatterns = [
8 | path('', views.route, name="route"),
9 | path('map', views.map, name="map"),
10 | ]
11 |
--------------------------------------------------------------------------------
/main/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, redirect, reverse
2 | from django.conf import settings
3 |
4 | from .mixins import Directions
5 | '''
6 | Basic view for routing
7 | '''
8 | def route(request):
9 |
10 | context = {"google_api_key": settings.API_KEY}
11 | return render(request, 'main/route.html', context)
12 |
13 |
14 | '''
15 | Basic view for displaying a map
16 | '''
17 | def map(request):
18 |
19 | lat_a = request.GET.get("lat_a", None)
20 | long_a = request.GET.get("long_a", None)
21 | lat_b = request.GET.get("lat_b", None)
22 | long_b = request.GET.get("long_b", None)
23 | lat_c = request.GET.get("lat_c", None)
24 | long_c = request.GET.get("long_c", None)
25 | lat_d = request.GET.get("lat_d", None)
26 | long_d = request.GET.get("long_d", None)
27 |
28 |
29 | #only call API if all 4 addresses are added
30 | if lat_a and lat_b and lat_c and lat_d:
31 | directions = Directions(
32 | lat_a= lat_a,
33 | long_a=long_a,
34 | lat_b = lat_b,
35 | long_b=long_b,
36 | lat_c= lat_c,
37 | long_c=long_c,
38 | lat_d = lat_d,
39 | long_d=long_d
40 | )
41 | else:
42 | return redirect(reverse('main:route'))
43 |
44 | context = {
45 | "google_api_key": settings.API_KEY,
46 | "lat_a": lat_a,
47 | "long_a": long_a,
48 | "lat_b": lat_b,
49 | "long_b": long_b,
50 | "lat_c": lat_c,
51 | "long_c": long_c,
52 | "lat_d": lat_d,
53 | "long_d": long_d,
54 | "origin": f'{lat_a}, {long_a}',
55 | "destination": f'{lat_b}, {long_b}',
56 | "directions": directions,
57 |
58 | }
59 | return render(request, 'main/map.html', context)
60 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'did_django_google_waypoints.settings')
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | asgiref==3.3.4
2 | certifi==2020.12.5
3 | chardet==4.0.0
4 | Django==3.2.2
5 | django-decouple==2.1
6 | humanfriendly==9.1
7 | idna==2.10
8 | pyreadline==2.1
9 | pytz==2021.1
10 | requests==2.25.1
11 | sqlparse==0.4.1
12 | typing-extensions==3.10.0.0
13 | urllib3==1.26.4
14 |
--------------------------------------------------------------------------------
/static/branding/did-logo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/static/branding/did-logo.gif
--------------------------------------------------------------------------------
/static/branding/did_logo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/static/branding/did_logo.gif
--------------------------------------------------------------------------------
/static/branding/did_logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/static/branding/did_logo.jpg
--------------------------------------------------------------------------------
/static/branding/did_logo.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/static/branding/did_logo.mp4
--------------------------------------------------------------------------------
/static/branding/did_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobby-didcoding/did_django_google_waypoints/7da71f9befcf76599b15baf15cded4485cc03e90/static/branding/did_logo.png
--------------------------------------------------------------------------------
/static/google_maps.js:
--------------------------------------------------------------------------------
1 |
2 | $.getScript( "https://maps.googleapis.com/maps/api/js?key=" + google_api_key + "&libraries=places")
3 | .done(function( script, textStatus ) {
4 | google.maps.event.addDomListener(window, "load", initMap)
5 |
6 | })
7 |
8 |
9 | function initMap() {
10 | var directionsService = new google.maps.DirectionsService;
11 | var directionsDisplay = new google.maps.DirectionsRenderer;
12 | var map = new google.maps.Map(document.getElementById('map-route'), {
13 | zoom: 7,
14 | center: {lat: lat_a, lng: long_a}
15 | });
16 | directionsDisplay.setMap(map);
17 | calculateAndDisplayRoute(directionsService, directionsDisplay);
18 |
19 | }
20 |
21 | const waypts = [
22 | {location: {lat: lat_c, lng: long_c},
23 | stopover: true},
24 | {location: {lat: lat_d, lng: long_d},
25 | stopover: true}
26 | ];
27 |
28 | function calculateAndDisplayRoute(directionsService, directionsDisplay) {
29 | directionsService.route({
30 | origin: origin,
31 | destination: destination,
32 | waypoints: waypts,
33 | optimizeWaypoints: true,
34 | travelMode: google.maps.TravelMode.DRIVING,
35 | }, function(response, status) {
36 | if (status === 'OK') {
37 | directionsDisplay.setDirections(response);
38 |
39 |
40 | } else {
41 |
42 | alert('Directions request failed due to ' + status);
43 | window.location.assign("/route")
44 | }
45 | });
46 | }
--------------------------------------------------------------------------------
/static/google_places.js:
--------------------------------------------------------------------------------
1 |
2 | $.getScript( "https://maps.googleapis.com/maps/api/js?key=" + google_api_key + "&libraries=places")
3 | .done(function( script, textStatus ) {
4 | google.maps.event.addDomListener(window, "load", initAutocomplete())
5 |
6 | })
7 |
8 | var auto_fields = ['a', 'b', 'c', 'd']
9 |
10 | function initAutocomplete() {
11 |
12 | for (i = 0; i < auto_fields.length; i++) {
13 | var field = auto_fields[i]
14 | window['autocomplete_'+field] = new google.maps.places.Autocomplete(
15 | document.getElementById('id-google-address-' + field),
16 | {
17 | types: ['address'],
18 | componentRestrictions: {'country': ['uk']},
19 | })
20 | }
21 |
22 | autocomplete_a.addListener('place_changed', function(){
23 | onPlaceChanged('a')
24 | });
25 | autocomplete_b.addListener('place_changed', function(){
26 | onPlaceChanged('b')
27 | });
28 | autocomplete_c.addListener('place_changed', function(){
29 | onPlaceChanged('c')
30 | });
31 | autocomplete_d.addListener('place_changed', function(){
32 | onPlaceChanged('d')
33 | });
34 | }
35 |
36 |
37 | function onPlaceChanged (addy){
38 |
39 | var auto = window['autocomplete_'+addy]
40 | var el_id = 'id-google-address-'+addy
41 | var lat_id = 'id-lat-' + addy
42 | var long_id = 'id-long-' + addy
43 |
44 | var geocoder = new google.maps.Geocoder()
45 | var address = document.getElementById(el_id).value
46 |
47 | geocoder.geocode( { 'address': address}, function(results, status) {
48 |
49 | if (status == google.maps.GeocoderStatus.OK) {
50 | var latitude = results[0].geometry.location.lat();
51 | var longitude = results[0].geometry.location.lng();
52 |
53 | $('#' + lat_id).val(latitude)
54 | $('#' + long_id).val(longitude)
55 |
56 | CalcRoute()
57 | }
58 | });
59 | }
60 |
61 |
62 | function validateForm() {
63 | var valid = true;
64 | $('.geo').each(function () {
65 | if ($(this).val() === '') {
66 | valid = false;
67 | return false;
68 | }
69 | });
70 | return valid
71 | }
72 |
73 |
74 | function CalcRoute(){
75 |
76 | if ( validateForm() == true){
77 | var params = {
78 | lat_a: $('#id-lat-a').val(),
79 | long_a: $('#id-long-a').val(),
80 | lat_b: $('#id-lat-b').val(),
81 | long_b: $('#id-long-b').val(),
82 | lat_c: $('#id-lat-c').val(),
83 | long_c: $('#id-long-c').val(),
84 | lat_d: $('#id-lat-d').val(),
85 | long_d: $('#id-long-d').val(),
86 | };
87 |
88 | var esc = encodeURIComponent;
89 | var query = Object.keys(params)
90 | .map(k => esc(k) + '=' + esc(params[k]))
91 | .join('&');
92 |
93 | url = '/map?' + query
94 | window.location.assign(url)
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/static/main.css:
--------------------------------------------------------------------------------
1 | body {font-family: 'Courier Prime', monospace;}
2 | * {box-sizing: border-box;}
3 |
4 | body {
5 |
6 | margin: 0;
7 | }
8 |
9 | body, html, .map-container {
10 | height: 100%;
11 | }
12 |
13 | #map-route {
14 | height: 75%;
15 | }
16 |
17 | .logo {
18 | width: 150px;
19 | padding: 8px;
20 | }
21 |
22 |
23 | ul.sidenav {
24 | list-style-type: none;
25 | margin: 0;
26 | padding: 0;
27 | width: 25%;
28 | background-color: #f1f1f1;
29 | position: fixed;
30 | height: 100%;
31 | overflow: auto;
32 | }
33 |
34 | ul.sidenav li a {
35 | display: block;
36 | color: #000;
37 | padding: 8px 16px;
38 | text-decoration: none;
39 | }
40 |
41 | ul.sidenav li a.active {
42 | background-color: #9c07b6;
43 | color: white;
44 | }
45 |
46 | ul.sidenav li a:hover:not(.active) {
47 | background-color: #555;
48 | color: white;
49 | }
50 |
51 | .div-container {
52 |
53 | margin-left: 25%;
54 | padding: 1px 16px;
55 | height: 1000px;
56 | }
57 |
58 | @media screen and (max-width: 900px) {
59 | ul.sidenav {
60 | width: 100%;
61 | height: auto;
62 | position: relative;
63 | }
64 |
65 | ul.sidenav li a {
66 | float: left;
67 | padding: 15px;
68 | }
69 |
70 | .div-container {margin-left: 0;}
71 | }
72 |
73 | @media screen and (max-width: 400px) {
74 | ul.sidenav li a {
75 | text-align: center;
76 | float: none;
77 | }
78 | }
79 |
80 | input[type=text], input[type=email], input[type=password], select, textarea {
81 | width: 100%;
82 | padding: 12px;
83 | border: 1px solid #ccc;
84 | border-radius: 4px;
85 | box-sizing: border-box;
86 | margin-top: 6px;
87 | margin-bottom: 16px;
88 | resize: vertical;
89 | }
90 |
91 |
92 | ::-webkit-input-placeholder { /* Edge */
93 | color: #9c07b6;
94 | font-family: 'Courier Prime', monospace;
95 | }
96 |
97 | :-ms-input-placeholder { /* Internet Explorer */
98 | color: #9c07b6;
99 | font-family: 'Courier Prime', monospace;
100 | }
101 |
102 | ::placeholder {
103 | color: #9c07b6;
104 | font-family: 'Courier Prime', monospace;
105 | }
106 |
107 | select.selection option,
108 | {
109 | color: #9c07b6;
110 | font-family: 'Courier Prime', monospace;
111 | }
112 |
113 | input, select{
114 | color: #9c07b6;
115 | font-family: 'Courier Prime', monospace;
116 |
117 | }
118 |
119 | /* The container */
120 | .check-container {
121 | display: block;
122 | position: relative;
123 | padding-left: 35px;
124 | margin-bottom: 12px;
125 | cursor: pointer;
126 | -webkit-user-select: none;
127 | -moz-user-select: none;
128 | -ms-user-select: none;
129 | user-select: none;
130 | }
131 |
132 | /* Hide the browser's default checkbox */
133 | .check-container input {
134 | position: absolute;
135 | opacity: 0;
136 | cursor: pointer;
137 | height: 0;
138 | width: 0;
139 | }
140 |
141 | /* Create a custom checkbox */
142 | .checkmark {
143 | position: absolute;
144 | top: 0;
145 | left: 0;
146 | height: 15px;
147 | width: 15px;
148 | background-color: #fff;
149 | }
150 |
151 | /* On mouse-over, add a grey background color */
152 | .check-container:hover input ~ .checkmark {
153 | background-color: #ccc;
154 | }
155 |
156 | /* When the checkbox is checked, add a green background */
157 | .check-container input:checked ~ .checkmark {
158 | background-color: #9c07b6;
159 | }
160 |
161 | /* Create the checkmark/indicator (hidden when not checked) */
162 | .check-container:after {
163 | content: "";
164 | position: absolute;
165 | display: none;
166 | }
167 |
168 | /* Show the checkmark when checked */
169 | .check-container input:checked ~ .checkmark:after {
170 | display: block;
171 | }
172 |
173 | /* Style the checkmark/indicator */
174 | .check-container .checkmark:after {
175 | left: 9px;
176 | top: 5px;
177 | width: 5px;
178 | height: 10px;
179 | border: solid white;
180 | border-width: 0 3px 3px 0;
181 | -webkit-transform: rotate(45deg);
182 | -ms-transform: rotate(45deg);
183 | transform: rotate(45deg);
184 | }
185 |
186 | .switch {
187 | position: relative;
188 | display: inline-block;
189 | width: 60px;
190 | height: 34px;
191 | }
192 |
193 | /* Hide default HTML checkbox */
194 | .switch input {
195 | opacity: 0;
196 | width: 0;
197 | height: 0;
198 | }
199 |
200 | /* The slider */
201 | .slider {
202 | position: absolute;
203 | cursor: pointer;
204 | top: 0;
205 | left: 0;
206 | right: 0;
207 | bottom: 0;
208 | background-color: #ccc;
209 | -webkit-transition: .4s;
210 | transition: .4s;
211 | }
212 |
213 | .slider:before {
214 | position: absolute;
215 | content: "";
216 | height: 26px;
217 | width: 26px;
218 | left: 4px;
219 | bottom: 4px;
220 | background-color: white;
221 | -webkit-transition: .4s;
222 | transition: .4s;
223 | }
224 |
225 | input:checked + .slider {
226 | background-color: #9c07b6;
227 | }
228 |
229 | input:focus + .slider {
230 | box-shadow: 0 0 1px #9c07b6;
231 | }
232 |
233 | input:checked + .slider:before {
234 | -webkit-transform: translateX(26px);
235 | -ms-transform: translateX(26px);
236 | transform: translateX(26px);
237 | }
238 |
239 | /* Rounded sliders */
240 | .slider.round {
241 | border-radius: 34px;
242 | }
243 |
244 | .slider.round:before {
245 | border-radius: 50%;
246 | }
247 |
248 | button[type=submit] {
249 | background-color: #9c07b6;
250 | color: white;
251 | padding: 12px 20px;
252 | border: none;
253 | border-radius: 4px;
254 | cursor: pointer;
255 | }
256 |
257 | button[type=submit]:hover {
258 | background-color: #730786;
259 | }
260 |
261 | .container {
262 | border-radius: 5px;
263 | background-color: #f2f2f2;
264 | padding: 20px;
265 | }
266 |
267 | table {
268 | font-family: 'Courier Prime', monospace;
269 | border-collapse: collapse;
270 | width: 100%;
271 | }
272 |
273 | table td, table th {
274 | border: 1px solid #ddd;
275 | padding: 8px;
276 | }
277 |
278 | table tr:hover {background-color: #ddd;}
279 |
280 | table th {
281 | padding-top: 12px;
282 | padding-bottom: 12px;
283 | text-align: left;
284 | background-color: #9c07b6;
285 | color: white;
286 | }
287 |
288 | .selected {
289 | background-color: #730786;
290 | color: #FFF;
291 | }
292 |
293 | #payment-form {
294 | width: 100%;
295 | }
296 |
297 | /* style inputs and link buttons */
298 | input, select,
299 | .btn {
300 | width: 100%;
301 | padding: 12px;
302 | border: none;
303 | border-radius: 4px;
304 | margin: 5px 0;
305 | opacity: 0.85;
306 | display: inline-block;
307 | font-size: 17px;
308 | line-height: 20px;
309 | text-decoration: none; /* remove underline from anchors */
310 | }
311 |
312 | input:hover,
313 | .btn:hover {
314 | opacity: 1;
315 | }
--------------------------------------------------------------------------------
/static/main.js:
--------------------------------------------------------------------------------
1 | function DirectionsToggle(){
2 | var el = $('#dir-toggle');
3 | var dir_table = $('#dir-table')
4 | if (dir_table.attr("hidden") == "hidden") {
5 | dir_table.fadeIn()
6 | dir_table.removeAttr("hidden")
7 | el.html('hide here')
8 | } else {
9 | dir_table.fadeOut()
10 | dir_table.attr("hidden", "hidden")
11 | el.html('click here')
12 | }
13 | }
14 |
15 | // 99978
16 |
17 |
--------------------------------------------------------------------------------