First attempt to upgrade to Django 3.X

Bloqued by https://github.com/peopledoc/django-agnocomplete/issues/119
This commit is contained in:
Yohan Boniface 2021-05-17 10:51:24 +02:00
parent 956549e5da
commit 1200b82838
12 changed files with 70 additions and 65 deletions

View file

@ -1,4 +1,4 @@
factory-boy==2.12.0 factory-boy==3.2.0
mkdocs==1.1 mkdocs==1.1.2
pytest==5.4.1 pytest==6.2.4
pytest-django==3.8.0 pytest-django==4.3.0

View file

@ -1,8 +1,8 @@
Django==2.2.17 Django==3.2.3
django-agnocomplete==1.0.0 django-agnocomplete==1.0.0
django-compressor==2.4 django-compressor==2.4.1
Pillow==8.0.1 Pillow==8.2.0
psycopg2==2.8.4 psycopg2==2.8.6
requests==2.23.0 requests==2.25.1
social-auth-core==3.3.2 social-auth-core==4.1.0
social-auth-app-django==3.1.0 social-auth-app-django==4.0.0

View file

@ -1,6 +1,6 @@
import json import json
from django.utils import six import six
from django.db import models from django.db import models
from django.utils.encoding import smart_text from django.utils.encoding import smart_text

View file

@ -1,7 +1,7 @@
from django import forms from django import forms
from django.contrib.gis.geos import Point from django.contrib.gis.geos import Point
from django.contrib.auth import get_user_model 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.template.defaultfilters import slugify
from django.conf import settings from django.conf import settings
from django.forms.utils import ErrorList from django.forms.utils import ErrorList

View file

@ -1,7 +1,7 @@
from django.conf import settings from django.conf import settings
from django.core.exceptions import MiddlewareNotUsed from django.core.exceptions import MiddlewareNotUsed
from django.http import HttpResponseForbidden from django.http import HttpResponseForbidden
from django.utils.translation import ugettext as _ from django.utils.translation import gettext as _
def readonly_middleware(get_response): def readonly_middleware(get_response):

View file

@ -4,7 +4,7 @@ import time
from django.contrib.gis.db import models from django.contrib.gis.db import models
from django.conf import settings from django.conf import settings
from django.urls import reverse 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.core.signing import Signer
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from django.core.files.base import File from django.core.files.base import File

View file

@ -1,6 +1,6 @@
import imp
import os import os
import sys import sys
import types
from django.utils.termcolors import colorize from django.utils.termcolors import colorize
@ -22,7 +22,7 @@ if not path:
print(colorize(msg, fg='red')) print(colorize(msg, fg='red'))
sys.exit(1) sys.exit(1)
d = imp.new_module('config') d = types.ModuleType('config')
d.__file__ = path d.__file__ = path
try: try:
with open(path) as config_file: with open(path) as config_file:

View file

@ -1,6 +1,5 @@
"""Base settings shared by all environments""" """Base settings shared by all environments"""
# Import global settings to make it easier to extend settings. # 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.template.defaultfilters import slugify
from django.conf.locale import LANG_INFO from django.conf.locale import LANG_INFO
@ -130,8 +129,10 @@ STATIC_ROOT = os.path.join('static')
MEDIA_ROOT = os.path.join('uploads') MEDIA_ROOT = os.path.join('uploads')
STATICFILES_FINDERS = [ STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'compressor.finders.CompressorFinder', 'compressor.finders.CompressorFinder',
] + STATICFILES_FINDERS ]
# ============================================================================= # =============================================================================
# Templates # Templates

View file

@ -10,14 +10,14 @@ from umap.models import DataLayer, Licence, Map, TileLayer
User = get_user_model() User = get_user_model()
class LicenceFactory(factory.DjangoModelFactory): class LicenceFactory(factory.django.DjangoModelFactory):
name = "WTFPL" name = "WTFPL"
class Meta: class Meta:
model = Licence model = Licence
class TileLayerFactory(factory.DjangoModelFactory): class TileLayerFactory(factory.django.DjangoModelFactory):
name = "Test zoom layer" name = "Test zoom layer"
url_template = "http://{s}.test.org/{z}/{x}/{y}.png" url_template = "http://{s}.test.org/{z}/{x}/{y}.png"
attribution = "Test layer attribution" attribution = "Test layer attribution"
@ -26,7 +26,7 @@ class TileLayerFactory(factory.DjangoModelFactory):
model = TileLayer model = TileLayer
class UserFactory(factory.DjangoModelFactory): class UserFactory(factory.django.DjangoModelFactory):
username = 'Joe' username = 'Joe'
email = factory.LazyAttribute( email = factory.LazyAttribute(
lambda a: '{0}@example.com'.format(a.username).lower()) lambda a: '{0}@example.com'.format(a.username).lower())
@ -36,7 +36,7 @@ class UserFactory(factory.DjangoModelFactory):
model = User model = User
class MapFactory(factory.DjangoModelFactory): class MapFactory(factory.django.DjangoModelFactory):
name = "test map" name = "test map"
slug = "test-map" slug = "test-map"
center = DEFAULT_CENTER center = DEFAULT_CENTER
@ -76,7 +76,7 @@ class MapFactory(factory.DjangoModelFactory):
model = Map model = Map
class DataLayerFactory(factory.DjangoModelFactory): class DataLayerFactory(factory.django.DjangoModelFactory):
map = factory.SubFactory(MapFactory) map = factory.SubFactory(MapFactory)
name = "test datalayer" name = "test datalayer"
description = "test description" description = "test description"

View file

@ -1,5 +1,5 @@
from django.conf import settings 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.i18n import i18n_patterns
from django.conf.urls.static import static from django.conf.urls.static import static
from django.contrib import admin from django.contrib import admin
@ -17,74 +17,74 @@ from .utils import decorated_patterns
admin.autodiscover() admin.autodiscover()
urlpatterns = [ urlpatterns = [
url(r'^admin/', admin.site.urls), re_path(r'^admin/', admin.site.urls),
url('', include('social_django.urls', namespace='social')), re_path('', include('social_django.urls', namespace='social')),
url(r'^m/(?P<pk>\d+)/$', views.MapShortUrl.as_view(), re_path(r'^m/(?P<pk>\d+)/$', views.MapShortUrl.as_view(),
name='map_short_url'), 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'), 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'}, {'template_name': 'umap/password_change.html'},
name='password_change'), 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'}, {'template_name': 'umap/password_change_done.html'},
name='password_change_done'), name='password_change_done'),
url(r'^i18n/', include('django.conf.urls.i18n')), re_path(r'^i18n/', include('django.conf.urls.i18n')),
url(r'^agnocomplete/', include('agnocomplete.urls')), re_path(r'^agnocomplete/', include('agnocomplete.urls')),
] ]
i18n_urls = [ i18n_urls = [
url(r'^login/$', jsonize_view(auth_views.LoginView.as_view()), name='login'), # noqa re_path(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/popup/end/$', views.LoginPopupEnd.as_view(),
name='login_popup_end'), name='login_popup_end'),
url(r'^logout/$', views.logout, name='logout'), re_path(r'^logout/$', views.logout, name='logout'),
url(r'^map/(?P<pk>\d+)/geojson/$', views.MapViewGeoJSON.as_view(), re_path(r'^map/(?P<pk>\d+)/geojson/$', views.MapViewGeoJSON.as_view(),
name='map_geojson'), 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'), 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'), name='pictogram_list_json'),
] ]
i18n_urls += decorated_patterns(cache_control(must_revalidate=True), i18n_urls += decorated_patterns(cache_control(must_revalidate=True),
url(r'^datalayer/(?P<pk>[\d]+)/$', views.DataLayerView.as_view(), name='datalayer_view'), # noqa re_path(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 re_path(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]+)/(?P<name>[_\w]+.geojson)$', views.DataLayerVersion.as_view(), name='datalayer_version'), # noqa
) )
i18n_urls += decorated_patterns([ensure_csrf_cookie], i18n_urls += decorated_patterns([ensure_csrf_cookie],
url(r'^map/(?P<slug>[-_\w]+)_(?P<pk>\d+)$', views.MapView.as_view(), name='map'), # noqa re_path(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/new/$', views.MapNew.as_view(), name='map_new'),
) )
i18n_urls += decorated_patterns( i18n_urls += decorated_patterns(
[login_required_if_not_anonymous_allowed, never_cache], [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( i18n_urls += decorated_patterns(
[map_permissions_check, never_cache], [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'), 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'), 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'), 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'), 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'), 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'), 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'), 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'), views.DataLayerDelete.as_view(), name='datalayer_delete'),
) )
urlpatterns += i18n_patterns( urlpatterns += i18n_patterns(
url(r'^$', views.home, name="home"), re_path(r'^$', views.home, name="home"),
url(r'^showcase/$', cache_page(24 * 60 * 60)(views.showcase), re_path(r'^showcase/$', cache_page(24 * 60 * 60)(views.showcase),
name='maps_showcase'), name='maps_showcase'),
url(r'^search/$', views.search, name="search"), re_path(r'^search/$', views.search, name="search"),
url(r'^about/$', views.about, name="about"), re_path(r'^about/$', views.about, name="about"),
url(r'^user/(?P<username>.+)/$', views.user_maps, name='user_maps'), re_path(r'^user/(?P<username>.+)/$', views.user_maps, name='user_maps'),
url(r'', include(i18n_urls)), re_path(r'', include(i18n_urls)),
) )
if settings.DEBUG and settings.MEDIA_ROOT: if settings.DEBUG and settings.MEDIA_ROOT:

View file

@ -109,3 +109,7 @@ def gzip_file(from_path, to_path):
with open(from_path, 'rb') as f_in: with open(from_path, 'rb') as f_in:
with gzip.open(to_path, 'wb') as f_out: with gzip.open(to_path, 'wb') as f_out:
f_out.writelines(f_in) f_out.writelines(f_in)
def is_ajax(request):
return request.headers.get('x-requested-with') == 'XMLHttpRequest'

View file

@ -23,7 +23,7 @@ from django.template.loader import render_to_string
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.utils.encoding import force_bytes, smart_bytes from django.utils.encoding import force_bytes, smart_bytes
from django.utils.http import http_date 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.utils.translation import to_locale
from django.views.generic import DetailView, TemplateView, View from django.views.generic import DetailView, TemplateView, View
from django.views.generic.base import RedirectView from django.views.generic.base import RedirectView
@ -35,7 +35,7 @@ from .forms import (DEFAULT_LATITUDE, DEFAULT_LONGITUDE, DEFAULT_CENTER,
AnonymousMapPermissionsForm, DataLayerForm, FlatErrorList, AnonymousMapPermissionsForm, DataLayerForm, FlatErrorList,
MapSettingsForm, UpdateMapPermissionsForm) MapSettingsForm, UpdateMapPermissionsForm)
from .models import DataLayer, Licence, Map, Pictogram, TileLayer 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: try:
# python3 # python3
@ -116,7 +116,7 @@ class Home(TemplateView, PaginatorMixin):
""" """
Dispatch template according to the kind of request: ajax or normal. 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] return [self.list_template_name]
else: else:
return [self.template_name] return [self.template_name]
@ -159,7 +159,7 @@ class UserMaps(DetailView, PaginatorMixin):
""" """
Dispatch template according to the kind of request: ajax or normal. 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] return [self.list_template_name]
else: else:
return super(UserMaps, self).get_template_names() 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. 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] return [self.list_template_name]
else: else:
return super(Search, self).get_template_names() return super(Search, self).get_template_names()
@ -239,7 +239,7 @@ showcase = MapsShowCase.as_view()
def validate_url(request): def validate_url(request):
assert request.method == "GET" assert request.method == "GET"
assert request.is_ajax() assert is_ajax(request)
url = request.GET.get('url') url = request.GET.get('url')
assert url assert url
try: try: