Merge branch 'dj3'
This commit is contained in:
commit
e6b02724eb
14 changed files with 92 additions and 74 deletions
15
.travis.yml
15
.travis.yml
|
@ -1,21 +1,22 @@
|
|||
sudo: false
|
||||
os: linux
|
||||
language: python
|
||||
dist: xenial
|
||||
dist: focal
|
||||
python:
|
||||
- "3.6"
|
||||
- "3.7"
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
services:
|
||||
- postgresql
|
||||
- postgresql
|
||||
addons:
|
||||
postgresql: "9.6"
|
||||
apt:
|
||||
packages:
|
||||
- libgdal-dev
|
||||
- postgresql-9.6-postgis-2.4
|
||||
- postgresql-12-postgis-3
|
||||
env:
|
||||
- UMAP_SETTINGS=umap/tests/settings.py
|
||||
global:
|
||||
- PGPORT=5432
|
||||
- UMAP_SETTINGS=umap/tests/settings.py
|
||||
install:
|
||||
- pip install .
|
||||
- pip install -r requirements-dev.txt
|
||||
|
@ -23,7 +24,7 @@ script: make test
|
|||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- "irc.freenode.net#umap"
|
||||
- "irc.libera.chat#umap"
|
||||
on_success: change
|
||||
on_failure: always
|
||||
email: false
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
factory-boy==2.12.0
|
||||
mkdocs==1.1
|
||||
pytest==5.4.1
|
||||
pytest-django==3.8.0
|
||||
factory-boy==3.2.0
|
||||
mkdocs==1.1.2
|
||||
pytest==6.2.4
|
||||
pytest-django==4.3.0
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
Django==2.2.17
|
||||
Django==3.2.3
|
||||
django-agnocomplete==1.0.0
|
||||
django-compressor==2.4
|
||||
Pillow==8.0.1
|
||||
psycopg2==2.8.4
|
||||
requests==2.23.0
|
||||
social-auth-core==3.3.2
|
||||
social-auth-app-django==3.1.0
|
||||
django-compressor==2.4.1
|
||||
Pillow==8.2.0
|
||||
psycopg2==2.8.6
|
||||
requests==2.25.1
|
||||
social-auth-core==4.1.0
|
||||
social-auth-app-django==4.0.0
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import json
|
||||
|
||||
from django.utils import six
|
||||
import six
|
||||
from django.db import models
|
||||
from django.utils.encoding import smart_text
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django import forms
|
||||
from django.contrib.gis.geos import Point
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.conf import settings
|
||||
from django.forms.utils import ErrorList
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.conf import settings
|
||||
from django.core.exceptions import MiddlewareNotUsed
|
||||
from django.http import HttpResponseForbidden
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
|
||||
def readonly_middleware(get_response):
|
||||
|
|
|
@ -4,7 +4,7 @@ import time
|
|||
from django.contrib.gis.db import models
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.signing import Signer
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.core.files.base import File
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import imp
|
||||
import os
|
||||
import sys
|
||||
import types
|
||||
|
||||
from django.utils.termcolors import colorize
|
||||
|
||||
|
@ -22,7 +22,7 @@ if not path:
|
|||
print(colorize(msg, fg='red'))
|
||||
sys.exit(1)
|
||||
|
||||
d = imp.new_module('config')
|
||||
d = types.ModuleType('config')
|
||||
d.__file__ = path
|
||||
try:
|
||||
with open(path) as config_file:
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
"""Base settings shared by all environments"""
|
||||
# Import global settings to make it easier to extend settings.
|
||||
from django.conf.global_settings import * # pylint: disable=W0614,W0401
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.conf.locale import LANG_INFO
|
||||
|
||||
|
@ -130,8 +129,10 @@ STATIC_ROOT = os.path.join('static')
|
|||
MEDIA_ROOT = os.path.join('uploads')
|
||||
|
||||
STATICFILES_FINDERS = [
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
'compressor.finders.CompressorFinder',
|
||||
] + STATICFILES_FINDERS
|
||||
]
|
||||
|
||||
# =============================================================================
|
||||
# Templates
|
||||
|
|
|
@ -10,14 +10,14 @@ from umap.models import DataLayer, Licence, Map, TileLayer
|
|||
User = get_user_model()
|
||||
|
||||
|
||||
class LicenceFactory(factory.DjangoModelFactory):
|
||||
class LicenceFactory(factory.django.DjangoModelFactory):
|
||||
name = "WTFPL"
|
||||
|
||||
class Meta:
|
||||
model = Licence
|
||||
|
||||
|
||||
class TileLayerFactory(factory.DjangoModelFactory):
|
||||
class TileLayerFactory(factory.django.DjangoModelFactory):
|
||||
name = "Test zoom layer"
|
||||
url_template = "http://{s}.test.org/{z}/{x}/{y}.png"
|
||||
attribution = "Test layer attribution"
|
||||
|
@ -26,7 +26,7 @@ class TileLayerFactory(factory.DjangoModelFactory):
|
|||
model = TileLayer
|
||||
|
||||
|
||||
class UserFactory(factory.DjangoModelFactory):
|
||||
class UserFactory(factory.django.DjangoModelFactory):
|
||||
username = 'Joe'
|
||||
email = factory.LazyAttribute(
|
||||
lambda a: '{0}@example.com'.format(a.username).lower())
|
||||
|
@ -36,7 +36,7 @@ class UserFactory(factory.DjangoModelFactory):
|
|||
model = User
|
||||
|
||||
|
||||
class MapFactory(factory.DjangoModelFactory):
|
||||
class MapFactory(factory.django.DjangoModelFactory):
|
||||
name = "test map"
|
||||
slug = "test-map"
|
||||
center = DEFAULT_CENTER
|
||||
|
@ -76,7 +76,7 @@ class MapFactory(factory.DjangoModelFactory):
|
|||
model = Map
|
||||
|
||||
|
||||
class DataLayerFactory(factory.DjangoModelFactory):
|
||||
class DataLayerFactory(factory.django.DjangoModelFactory):
|
||||
map = factory.SubFactory(MapFactory)
|
||||
name = "test datalayer"
|
||||
description = "test description"
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
from umap.settings.base import * # pylint: disable=W0614,W0401
|
||||
import os
|
||||
|
||||
SECRET_KEY = 'justfortests'
|
||||
from umap.settings.base import * # pylint: disable=W0614,W0401
|
||||
|
||||
SECRET_KEY = "justfortests"
|
||||
COMPRESS_ENABLED = False
|
||||
|
||||
if "TRAVIS" in os.environ:
|
||||
DATABASES = {
|
||||
"default": {
|
||||
"ENGINE": "django.contrib.gis.db.backends.postgis",
|
||||
"NAME": "umap",
|
||||
"PORT": 5433,
|
||||
"USER": "travis",
|
||||
}
|
||||
}
|
||||
|
|
70
umap/urls.py
70
umap/urls.py
|
@ -1,5 +1,5 @@
|
|||
from django.conf import settings
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include, re_path
|
||||
from django.conf.urls.i18n import i18n_patterns
|
||||
from django.conf.urls.static import static
|
||||
from django.contrib import admin
|
||||
|
@ -17,74 +17,74 @@ from .utils import decorated_patterns
|
|||
admin.autodiscover()
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^admin/', admin.site.urls),
|
||||
url('', include('social_django.urls', namespace='social')),
|
||||
url(r'^m/(?P<pk>\d+)/$', views.MapShortUrl.as_view(),
|
||||
re_path(r'^admin/', admin.site.urls),
|
||||
re_path('', include('social_django.urls', namespace='social')),
|
||||
re_path(r'^m/(?P<pk>\d+)/$', views.MapShortUrl.as_view(),
|
||||
name='map_short_url'),
|
||||
url(r'^ajax-proxy/$', cache_page(180)(views.ajax_proxy),
|
||||
re_path(r'^ajax-proxy/$', cache_page(180)(views.ajax_proxy),
|
||||
name='ajax-proxy'),
|
||||
url(r'^change-password/', auth_views.PasswordChangeView.as_view(),
|
||||
re_path(r'^change-password/', auth_views.PasswordChangeView.as_view(),
|
||||
{'template_name': 'umap/password_change.html'},
|
||||
name='password_change'),
|
||||
url(r'^change-password-done/', auth_views.PasswordChangeDoneView.as_view(),
|
||||
re_path(r'^change-password-done/', auth_views.PasswordChangeDoneView.as_view(),
|
||||
{'template_name': 'umap/password_change_done.html'},
|
||||
name='password_change_done'),
|
||||
url(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
url(r'^agnocomplete/', include('agnocomplete.urls')),
|
||||
re_path(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
re_path(r'^agnocomplete/', include('agnocomplete.urls')),
|
||||
]
|
||||
|
||||
i18n_urls = [
|
||||
url(r'^login/$', jsonize_view(auth_views.LoginView.as_view()), name='login'), # noqa
|
||||
url(r'^login/popup/end/$', views.LoginPopupEnd.as_view(),
|
||||
re_path(r'^login/$', jsonize_view(auth_views.LoginView.as_view()), name='login'), # noqa
|
||||
re_path(r'^login/popup/end/$', views.LoginPopupEnd.as_view(),
|
||||
name='login_popup_end'),
|
||||
url(r'^logout/$', views.logout, name='logout'),
|
||||
url(r'^map/(?P<pk>\d+)/geojson/$', views.MapViewGeoJSON.as_view(),
|
||||
re_path(r'^logout/$', views.logout, name='logout'),
|
||||
re_path(r'^map/(?P<pk>\d+)/geojson/$', views.MapViewGeoJSON.as_view(),
|
||||
name='map_geojson'),
|
||||
url(r'^map/anonymous-edit/(?P<signature>.+)$',
|
||||
re_path(r'^map/anonymous-edit/(?P<signature>.+)$',
|
||||
views.MapAnonymousEditUrl.as_view(), name='map_anonymous_edit_url'),
|
||||
url(r'^pictogram/json/$', views.PictogramJSONList.as_view(),
|
||||
re_path(r'^pictogram/json/$', views.PictogramJSONList.as_view(),
|
||||
name='pictogram_list_json'),
|
||||
]
|
||||
i18n_urls += decorated_patterns(cache_control(must_revalidate=True),
|
||||
url(r'^datalayer/(?P<pk>[\d]+)/$', views.DataLayerView.as_view(), name='datalayer_view'), # noqa
|
||||
url(r'^datalayer/(?P<pk>[\d]+)/versions/$', views.DataLayerVersions.as_view(), name='datalayer_versions'), # noqa
|
||||
url(r'^datalayer/(?P<pk>[\d]+)/(?P<name>[_\w]+.geojson)$', views.DataLayerVersion.as_view(), name='datalayer_version'), # noqa
|
||||
re_path(r'^datalayer/(?P<pk>[\d]+)/$', views.DataLayerView.as_view(), name='datalayer_view'), # noqa
|
||||
re_path(r'^datalayer/(?P<pk>[\d]+)/versions/$', views.DataLayerVersions.as_view(), name='datalayer_versions'), # noqa
|
||||
re_path(r'^datalayer/(?P<pk>[\d]+)/(?P<name>[_\w]+.geojson)$', views.DataLayerVersion.as_view(), name='datalayer_version'), # noqa
|
||||
)
|
||||
i18n_urls += decorated_patterns([ensure_csrf_cookie],
|
||||
url(r'^map/(?P<slug>[-_\w]+)_(?P<pk>\d+)$', views.MapView.as_view(), name='map'), # noqa
|
||||
url(r'^map/new/$', views.MapNew.as_view(), name='map_new'),
|
||||
re_path(r'^map/(?P<slug>[-_\w]+)_(?P<pk>\d+)$', views.MapView.as_view(), name='map'), # noqa
|
||||
re_path(r'^map/new/$', views.MapNew.as_view(), name='map_new'),
|
||||
)
|
||||
i18n_urls += decorated_patterns(
|
||||
[login_required_if_not_anonymous_allowed, never_cache],
|
||||
url(r'^map/create/$', views.MapCreate.as_view(), name='map_create'),
|
||||
re_path(r'^map/create/$', views.MapCreate.as_view(), name='map_create'),
|
||||
)
|
||||
i18n_urls += decorated_patterns(
|
||||
[map_permissions_check, never_cache],
|
||||
url(r'^map/(?P<map_id>[\d]+)/update/settings/$', views.MapUpdate.as_view(),
|
||||
re_path(r'^map/(?P<map_id>[\d]+)/update/settings/$', views.MapUpdate.as_view(),
|
||||
name='map_update'),
|
||||
url(r'^map/(?P<map_id>[\d]+)/update/permissions/$',
|
||||
re_path(r'^map/(?P<map_id>[\d]+)/update/permissions/$',
|
||||
views.UpdateMapPermissions.as_view(), name='map_update_permissions'),
|
||||
url(r'^map/(?P<map_id>[\d]+)/update/owner/$',
|
||||
re_path(r'^map/(?P<map_id>[\d]+)/update/owner/$',
|
||||
views.AttachAnonymousMap.as_view(), name='map_attach_owner'),
|
||||
url(r'^map/(?P<map_id>[\d]+)/update/delete/$',
|
||||
re_path(r'^map/(?P<map_id>[\d]+)/update/delete/$',
|
||||
views.MapDelete.as_view(), name='map_delete'),
|
||||
url(r'^map/(?P<map_id>[\d]+)/update/clone/$',
|
||||
re_path(r'^map/(?P<map_id>[\d]+)/update/clone/$',
|
||||
views.MapClone.as_view(), name='map_clone'),
|
||||
url(r'^map/(?P<map_id>[\d]+)/datalayer/create/$',
|
||||
re_path(r'^map/(?P<map_id>[\d]+)/datalayer/create/$',
|
||||
views.DataLayerCreate.as_view(), name='datalayer_create'),
|
||||
url(r'^map/(?P<map_id>[\d]+)/datalayer/update/(?P<pk>\d+)/$',
|
||||
re_path(r'^map/(?P<map_id>[\d]+)/datalayer/update/(?P<pk>\d+)/$',
|
||||
views.DataLayerUpdate.as_view(), name='datalayer_update'),
|
||||
url(r'^map/(?P<map_id>[\d]+)/datalayer/delete/(?P<pk>\d+)/$',
|
||||
re_path(r'^map/(?P<map_id>[\d]+)/datalayer/delete/(?P<pk>\d+)/$',
|
||||
views.DataLayerDelete.as_view(), name='datalayer_delete'),
|
||||
)
|
||||
urlpatterns += i18n_patterns(
|
||||
url(r'^$', views.home, name="home"),
|
||||
url(r'^showcase/$', cache_page(24 * 60 * 60)(views.showcase),
|
||||
re_path(r'^$', views.home, name="home"),
|
||||
re_path(r'^showcase/$', cache_page(24 * 60 * 60)(views.showcase),
|
||||
name='maps_showcase'),
|
||||
url(r'^search/$', views.search, name="search"),
|
||||
url(r'^about/$', views.about, name="about"),
|
||||
url(r'^user/(?P<username>.+)/$', views.user_maps, name='user_maps'),
|
||||
url(r'', include(i18n_urls)),
|
||||
re_path(r'^search/$', views.search, name="search"),
|
||||
re_path(r'^about/$', views.about, name="about"),
|
||||
re_path(r'^user/(?P<username>.+)/$', views.user_maps, name='user_maps'),
|
||||
re_path(r'', include(i18n_urls)),
|
||||
)
|
||||
|
||||
if settings.DEBUG and settings.MEDIA_ROOT:
|
||||
|
|
|
@ -109,3 +109,7 @@ def gzip_file(from_path, to_path):
|
|||
with open(from_path, 'rb') as f_in:
|
||||
with gzip.open(to_path, 'wb') as f_out:
|
||||
f_out.writelines(f_in)
|
||||
|
||||
|
||||
def is_ajax(request):
|
||||
return request.headers.get('x-requested-with') == 'XMLHttpRequest'
|
||||
|
|
|
@ -23,7 +23,7 @@ from django.template.loader import render_to_string
|
|||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils.encoding import force_bytes, smart_bytes
|
||||
from django.utils.http import http_date
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
from django.utils.translation import to_locale
|
||||
from django.views.generic import DetailView, TemplateView, View
|
||||
from django.views.generic.base import RedirectView
|
||||
|
@ -35,7 +35,7 @@ from .forms import (DEFAULT_LATITUDE, DEFAULT_LONGITUDE, DEFAULT_CENTER,
|
|||
AnonymousMapPermissionsForm, DataLayerForm, FlatErrorList,
|
||||
MapSettingsForm, UpdateMapPermissionsForm)
|
||||
from .models import DataLayer, Licence, Map, Pictogram, TileLayer
|
||||
from .utils import get_uri_template, gzip_file
|
||||
from .utils import get_uri_template, gzip_file, is_ajax
|
||||
|
||||
try:
|
||||
# python3
|
||||
|
@ -116,7 +116,7 @@ class Home(TemplateView, PaginatorMixin):
|
|||
"""
|
||||
Dispatch template according to the kind of request: ajax or normal.
|
||||
"""
|
||||
if self.request.is_ajax():
|
||||
if is_ajax(self.request):
|
||||
return [self.list_template_name]
|
||||
else:
|
||||
return [self.template_name]
|
||||
|
@ -159,7 +159,7 @@ class UserMaps(DetailView, PaginatorMixin):
|
|||
"""
|
||||
Dispatch template according to the kind of request: ajax or normal.
|
||||
"""
|
||||
if self.request.is_ajax():
|
||||
if is_ajax(self.request):
|
||||
return [self.list_template_name]
|
||||
else:
|
||||
return super(UserMaps, self).get_template_names()
|
||||
|
@ -192,7 +192,7 @@ class Search(TemplateView, PaginatorMixin):
|
|||
"""
|
||||
Dispatch template according to the kind of request: ajax or normal.
|
||||
"""
|
||||
if self.request.is_ajax():
|
||||
if is_ajax(self.request):
|
||||
return [self.list_template_name]
|
||||
else:
|
||||
return super(Search, self).get_template_names()
|
||||
|
@ -239,7 +239,7 @@ showcase = MapsShowCase.as_view()
|
|||
|
||||
def validate_url(request):
|
||||
assert request.method == "GET"
|
||||
assert request.is_ajax()
|
||||
assert is_ajax(request)
|
||||
url = request.GET.get('url')
|
||||
assert url
|
||||
try:
|
||||
|
|
Loading…
Reference in a new issue