diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..4644ece --- /dev/null +++ b/Pipfile @@ -0,0 +1,19 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] +psycopg2 = "*" + +[packages] +django = "*" +mercantile = "*" +geojson = "*" +djangorestframework = "*" +pyyaml = "*" +drf-yasg = "*" # django-rest-framework yet-another-swagger-generator required for documentation generation +dynamic-rest = "*" + +[requires] +python_version = "3" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..f7ddbf0 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,267 @@ +{ + "_meta": { + "hash": { + "sha256": "21f47a03e55fb16883db7e480e1877e0b11fb59fb36cb0177cb2117832cd09b7" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "certifi": { + "hashes": [ + "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", + "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" + ], + "version": "==2019.11.28" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "click": { + "hashes": [ + "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", + "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" + ], + "version": "==7.0" + }, + "coreapi": { + "hashes": [ + "sha256:46145fcc1f7017c076a2ef684969b641d18a2991051fddec9458ad3f78ffc1cb", + "sha256:bf39d118d6d3e171f10df9ede5666f63ad80bba9a29a8ec17726a66cf52ee6f3" + ], + "version": "==2.3.3" + }, + "coreschema": { + "hashes": [ + "sha256:5e6ef7bf38c1525d5e55a895934ab4273548629f16aed5c0a6caa74ebf45551f", + "sha256:9503506007d482ab0867ba14724b93c18a33b22b6d19fb419ef2d239dd4a1607" + ], + "version": "==0.0.4" + }, + "django": { + "hashes": [ + "sha256:1226168be1b1c7efd0e66ee79b0e0b58b2caa7ed87717909cd8a57bb13a7079a", + "sha256:9a4635813e2d498a3c01b10c701fe4a515d76dd290aaa792ccb65ca4ccb6b038" + ], + "index": "pypi", + "version": "==2.2.10" + }, + "djangorestframework": { + "hashes": [ + "sha256:5488aed8f8df5ec1d70f04b2114abc52ae6729748a176c453313834a9ee179c8", + "sha256:dc81cbf9775c6898a580f6f1f387c4777d12bd87abf0f5406018d32ccae71090" + ], + "index": "pypi", + "version": "==3.10.3" + }, + "drf-yasg": { + "hashes": [ + "sha256:4cfec631880ae527a91ec7cd3241aea2f82189f59e2f089119aa687761afb227", + "sha256:504cce09035cf1bace63b84d9d778b772f86bb37d8a71ed6f723346362e633b2" + ], + "index": "pypi", + "version": "==1.17.0" + }, + "dynamic-rest": { + "hashes": [ + "sha256:42abfc5f65d22b9c4ef70efa227bb940a7517421c5e97a0796c7bc998f99f745" + ], + "index": "pypi", + "version": "==1.9.6" + }, + "geojson": { + "hashes": [ + "sha256:6e4bb7ace4226a45d9c8c8b1348b3fc43540658359f93c3f7e03efa9f15f658a", + "sha256:ccbd13368dd728f4e4f13ffe6aaf725b6e802c692ba0dde628be475040c534ba" + ], + "index": "pypi", + "version": "==2.5.0" + }, + "idna": { + "hashes": [ + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + ], + "version": "==2.8" + }, + "inflection": { + "hashes": [ + "sha256:18ea7fb7a7d152853386523def08736aa8c32636b047ade55f7578c4edeb16ca" + ], + "version": "==0.3.1" + }, + "itypes": { + "hashes": [ + "sha256:c6e77bb9fd68a4bfeb9d958fea421802282451a25bac4913ec94db82a899c073" + ], + "version": "==1.1.0" + }, + "jinja2": { + "hashes": [ + "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250", + "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49" + ], + "version": "==2.11.1" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "version": "==1.1.1" + }, + "mercantile": { + "hashes": [ + "sha256:6681c0be3b3d8ea1d88d7f9cff56993782fb7de1e9df420ad9c48f93a859394d", + "sha256:6ef7301b8f5b29f622b97f5ab2c43edfa2e1c3857b96adbfc6eac9ec376abe0e" + ], + "index": "pypi", + "version": "==1.1.2" + }, + "packaging": { + "hashes": [ + "sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73", + "sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334" + ], + "version": "==20.1" + }, + "pyparsing": { + "hashes": [ + "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", + "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" + ], + "version": "==2.4.6" + }, + "pytz": { + "hashes": [ + "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", + "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be" + ], + "version": "==2019.3" + }, + "pyyaml": { + "hashes": [ + "sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6", + "sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf", + "sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5", + "sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e", + "sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811", + "sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e", + "sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d", + "sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20", + "sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689", + "sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994", + "sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615" + ], + "index": "pypi", + "version": "==5.3" + }, + "requests": { + "hashes": [ + "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", + "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" + ], + "version": "==2.22.0" + }, + "ruamel.yaml": { + "hashes": [ + "sha256:9d59fa89985c55155d35c886663e357813404ae8f94638cb673135b8c8c1a7c7", + "sha256:dba517a7e330b6caf476b757022d21efa13c32694bfba1e057ce59a374f18f0a" + ], + "version": "==0.16.7" + }, + "six": { + "hashes": [ + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + ], + "version": "==1.14.0" + }, + "sqlparse": { + "hashes": [ + "sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177", + "sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873" + ], + "version": "==0.3.0" + }, + "uritemplate": { + "hashes": [ + "sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f", + "sha256:5af8ad10cec94f215e3f48112de2022e1d5a37ed427fbd88652fa908f2ab7cae" + ], + "version": "==3.0.1" + }, + "urllib3": { + "hashes": [ + "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", + "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" + ], + "version": "==1.25.8" + } + }, + "develop": { + "psycopg2": { + "hashes": [ + "sha256:4212ca404c4445dc5746c0d68db27d2cbfb87b523fe233dc84ecd24062e35677", + "sha256:47fc642bf6f427805daf52d6e52619fe0637648fe27017062d898f3bf891419d", + "sha256:72772181d9bad1fa349792a1e7384dde56742c14af2b9986013eb94a240f005b", + "sha256:8396be6e5ff844282d4d49b81631772f80dabae5658d432202faf101f5283b7c", + "sha256:893c11064b347b24ecdd277a094413e1954f8a4e8cdaf7ffbe7ca3db87c103f0", + "sha256:92a07dfd4d7c325dd177548c4134052d4842222833576c8391aab6f74038fc3f", + "sha256:965c4c93e33e6984d8031f74e51227bd755376a9df6993774fd5b6fb3288b1f4", + "sha256:9ab75e0b2820880ae24b7136c4d230383e07db014456a476d096591172569c38", + "sha256:b0845e3bdd4aa18dc2f9b6fb78fbd3d9d371ad167fd6d1b7ad01c0a6cdad4fc6", + "sha256:dca2d7203f0dfce8ea4b3efd668f8ea65cd2b35112638e488a4c12594015f67b", + "sha256:ed686e5926929887e2c7ae0a700e32c6129abb798b4ad2b846e933de21508151", + "sha256:ef6df7e14698e79c59c7ee7cf94cd62e5b869db369ed4b1b8f7b729ea825712a", + "sha256:f898e5cc0a662a9e12bde6f931263a1bbd350cfb18e1d5336a12927851825bb6" + ], + "index": "pypi", + "version": "==2.8.4" + } + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..508bade --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Tileserver Mapping + +This is a django application whose role it is to keep track of available [Tileservers](https://github.com/Map-Data/regiontileserver), +the region which each one provides data for and route incoming traffic to the correct one. + + diff --git a/tileservermapping/mapping/models.py b/tileservermapping/mapping/models.py index e9c0e52..2c12a80 100644 --- a/tileservermapping/mapping/models.py +++ b/tileservermapping/mapping/models.py @@ -2,18 +2,6 @@ import mercantile -class Mapping(models.Model): - z = models.IntegerField(null=False) - x = models.IntegerField(null=False) - y = models.IntegerField(null=False) - land = models.IntegerField(null=False) #TODO: remodel to Forigin key to a country -> server mapping - - class Meta: - indexes = [ - models.Index(fields=['z', 'x', 'y']), - ] - - class Server(models.Model): z = models.IntegerField(null=False) x = models.IntegerField(null=False) diff --git a/tileservermapping/mapping/serializers.py b/tileservermapping/mapping/serializers.py new file mode 100644 index 0000000..075b837 --- /dev/null +++ b/tileservermapping/mapping/serializers.py @@ -0,0 +1,10 @@ +from dynamic_rest import serializers + +from . import models + + +class ServerSerializer(serializers.DynamicModelSerializer): + class Meta: + model = models.Server + fields = ["name", "x", "y", "z", "active", "scheme", "host", "url", "url_postfix"] + diff --git a/tileservermapping/mapping/urls.py b/tileservermapping/mapping/urls.py index d35abbd..d12cc14 100644 --- a/tileservermapping/mapping/urls.py +++ b/tileservermapping/mapping/urls.py @@ -1,8 +1,14 @@ -from django.conf.urls import url +from django.urls import path, include, re_path +from dynamic_rest import routers +from . import views from .views import get_server, get_cur_tiles +router = routers.DefaultRouter() +router.register(r"servers", views.ServerViewSet) + urlpatterns = [ - url(r'^vector/v1/512/all/(\d+)/(\d+)/(\d+)\.([a-zA-Z]+)$', get_server, name='mapping_server'), - url(r'^cur_tiles.js$', get_cur_tiles , name='mapping_get_cur_tiles'), + path("", include(router.urls)), + re_path(r'^vector/v1/512/all/(?P\d+)/(?P\d+)/(?P\d+)\.(?P[a-zA-Z]+)$', get_server, name='mapping_server'), + path(r'cur_tiles.js', get_cur_tiles , name='mapping_get_cur_tiles'), ] diff --git a/tileservermapping/mapping/views.py b/tileservermapping/mapping/views.py index 075bcca..72ce6cc 100644 --- a/tileservermapping/mapping/views.py +++ b/tileservermapping/mapping/views.py @@ -1,15 +1,27 @@ from django.http import HttpResponse +from dynamic_rest import viewsets from django.shortcuts import render from geojson import Polygon, Feature import mercantile +from rest_framework.decorators import api_view +from rest_framework.response import Response -# Create your views here. -from .models import Mapping, Server +from .models import Server +from . import serializers -def get_server(request, z, x, y, format): - response = HttpResponse() - response['X-Accel-Redirect'] = Server.get_redirect_server(int(z), int(x), int(y), format) +class ServerViewSet(viewsets.DynamicModelViewSet): + """ + API endpoint that allows servers to be viewed or edited + """ + queryset = Server.objects.all() + serializer_class = serializers.ServerSerializer + + +@api_view(http_method_names=["GET"]) +def get_server(request, z, x, y, file_ending): + response = Response() + response['X-Accel-Redirect'] = Server.get_redirect_server(int(z), int(x), int(y), file_ending) return response diff --git a/tileservermapping/settings.py.example b/tileservermapping/settings.py.example new file mode 100644 index 0000000..e205cd7 --- /dev/null +++ b/tileservermapping/settings.py.example @@ -0,0 +1,36 @@ +""" +Django settings for tileservermapping project. + +Generated by 'django-admin startproject' using Django 2.0.6. + +For more information on this file, see +https://docs.djangoproject.com/en/2.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/2.0/ref/settings/ +""" +from .settings_base import * + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = None # change this + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS += [ + "localhost" +] + +# Database +# https://docs.djangoproject.com/en/2.0/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'HOST': 'localhost', + 'PORT': 5432, + 'USER': 'osm_tileservermapping', + 'NAME': 'osm_tileservermapping', + 'PASSWORD': 'osm_tileservermapping' + } +} diff --git a/tileservermapping/settings_base.py b/tileservermapping/settings_base.py new file mode 100644 index 0000000..6f68050 --- /dev/null +++ b/tileservermapping/settings_base.py @@ -0,0 +1,124 @@ +""" +Django settings for tileservermapping project. + +Generated by 'django-admin startproject' using Django 2.0.6. + +For more information on this file, see +https://docs.djangoproject.com/en/2.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/2.0/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +ALLOWED_HOSTS = [ + # override in settings.py +] + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'rest_framework', + 'drf_yasg', + 'dynamic_rest', + 'tileservermapping.mapping', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'tileservermapping.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + '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', + ], + }, + }, +] + +WSGI_APPLICATION = 'tileservermapping.wsgi.application' + +DATABASES = { + # override in settings.py +} + +LOGIN_URL = "/admin/login/" +LOGOUT_URL = "/admin/logout/" +LOGOUT_REDIRECT_URL = "/" + +# Password validation +# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + +# Internationalization +# https://docs.djangoproject.com/en/2.0/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.0/howto/static-files/ + +STATIC_URL = '/static/' + + +# Django Rest Framework and extensions + +REST_FRAMEWORK = { + "DEFAULT_VERSION": "v1", + "ALLOWED_VERSIONS": ["v1"], + "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning", + "DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated"], +} + +DYNAMIC_REST = { + "ENABLE_BULK_UPDATE": False +} diff --git a/tileservermapping/urls.py b/tileservermapping/urls.py index a6e0db8..e72163e 100644 --- a/tileservermapping/urls.py +++ b/tileservermapping/urls.py @@ -1,23 +1,35 @@ """tileservermapping URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/2.0/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +https://docs.djangoproject.com/en/2.0/topics/http/urls/ """ -from django.conf.urls import url from django.contrib import admin from django.urls import path, include +from django.views.generic.base import RedirectView +from drf_yasg.views import get_schema_view +from drf_yasg import openapi + + +schema_view = get_schema_view( + openapi.Info( + title="Tileserver-Mapping Api", + description="Api to control the management of tileserver, their status and statistics", + default_version="v1", + contact=openapi.Contact("Nils Rokita, Finn-Thorben Sell"), + license=openapi.License("MIT", "https://github.com/Map-Data/tileserver-mapping/blob/master/LICENSE") + ), + public=True, + permission_classes=() +) + urlpatterns = [ - path('admin/', admin.site.urls), - url(r'^mappings/', include('tileservermapping.mapping.urls')), + path("api//", include("tileservermapping.mapping.urls")), + path("mappings/", include("tileservermapping.mapping.urls")), # included for compatibility to old url schema + + path("admin/", admin.site.urls), + path("schema/", schema_view.without_ui(cache_timeout=0), name="schema-json"), + path("docs/", schema_view.with_ui("swagger", cache_timeout=0), name="schema-swagger-ui"), + + path("", RedirectView.as_view(url="/docs")) ]