Skip to content

Commit

Permalink
Merge pull request #183 from makinacorpus/migration-django2
Browse files Browse the repository at this point in the history
Migration django2
  • Loading branch information
Gaël UTARD authored Jan 10, 2020
2 parents 8959303 + 7daac4d commit a3661ec
Show file tree
Hide file tree
Showing 35 changed files with 166 additions and 170 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ language: python

python:
- 3.5
- 3.6

env:
matrix:
- DJANGO_VERSION=1.11.*
- DJANGO_VERSION=2.0.*

install:
- sudo apt-get update
- ./install.sh
- ./env/bin/pip install --force-reinstall django==$DJANGO_VERSION
- ./env/bin/pip install coverage
- pip install flake8
- ./env/bin/python ./manage.py collectstatic --noinput
Expand Down
4 changes: 2 additions & 2 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ CHANGELOG
6.0.6.dev0
==================

**Bug fixes**
**Breaking changes**

-
- Upgrade to Django 2.0


6.0.5 (2019-12-20)
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ MapEntity
MapEntity is a CRUD interface for geospatial entities built with Django,
that powers `Geotrek <http://geotrek.fr>`_.

Works with Django 1.9 to 1.11.
Works with Python 3.5/3.6 and Django 2.0.

.. image:: https://img.shields.io/pypi/v/mapentity.svg
:target: https://pypi.python.org/pypi/mapentity
Expand Down
41 changes: 21 additions & 20 deletions docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Create your django Project and your main app::

$ django-admin.py startproject museum
$ cd museum/
$ python manage.py startapp main
$ python3 manage.py startapp main


Edit your Django settings to point to your PostGIS database::
Expand Down Expand Up @@ -43,7 +43,7 @@ Add these entries to your ``INSTALLED_APPS``::
'rest_framework',
'main', # the app you just created

Add ``django.middleware.locale.LocaleMiddleware`` to your ``MIDDLEWARE_CLASSES``.
Add ``django.middleware.locale.LocaleMiddleware`` to your ``MIDDLEWARE`` classes.

Setup your list of supported languages::

Expand All @@ -65,17 +65,19 @@ Specify a static root::
Add MapEntity and request context processors to the list of default context
processors::

TEMPLATE_CONTEXT_PROCESSORS = (
"django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.core.context_processors.tz",
"django.contrib.messages.context_processors.messages",
"django.core.context_processors.request",
"mapentity.context_processors.settings",
)
TEMPLATES = [
{
'OPTIONS': {
'context_processors': [
"django.core.context_processors.request",
"mapentity.context_processors.settings",
]
}
}
]


Model
Expand Down Expand Up @@ -140,13 +142,12 @@ Then glue everything together in your project's ``urls.py``:

urlpatterns = patterns(
| '',
| url(r'^$', 'main.views.home', name='home'),
| url(r'^login/$', 'django.contrib.auth.views.login', name='login'),
| url(r'^logout/$', 'django.contrib.auth.views.logout', name='logout',),
| url(r'', include('mapentity.urls', namespace='mapentity', app_name='mapentity')),
| url(r'^paperclip/', include('paperclip.urls')),
| url(r'', include('main.urls', namespace='main', app_name='main')),
| url(r'^admin/', include(admin.site.urls)),
| path('', 'main.views.home', name='home'),
| path('login/', 'django.contrib.auth.views.login', name='login'),
| path('logout/', 'django.contrib.auth.views.logout', name='logout',),
| path('', include('mapentity.urls')),
| path('paperclip/', include('paperclip.urls')),
| path('admin', admin.site.urls),
)


Expand Down
1 change: 1 addition & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ echo "--- Create virtualenv:"

echo "--- Install python requirements:"
./env/bin/pip install -U setuptools pip wheel
./env/bin/pip install Django==${DJANGO_VERSION:-2.0.*}
./env/bin/pip install -r requirements.txt
./env/bin/pip install -r dev-requirements.txt

Expand Down
2 changes: 1 addition & 1 deletion mapentity/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def check_perms(request, user, perm):
if user_has_perm(user, perm):
return True

if not user.is_anonymous() and raise_exception:
if not user.is_anonymous and raise_exception:
raise PermissionDenied

# As the last resort, redirects
Expand Down
9 changes: 9 additions & 0 deletions mapentity/filters.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.db.models import Q
from django.db.models.fields.related import ManyToOneRel
from django.conf import settings

Expand All @@ -19,6 +20,14 @@ def __init__(self, *args, **kwargs):
kwargs.setdefault('lookup_expr', 'intersects')
super(PolygonFilter, self).__init__(*args, **kwargs)

def filter(self, qs, value):
if not value:
return qs
return qs.filter(
Q(**{'{}__{}'.format(self.field_name, self.lookup_expr): value})
| Q(**{'{}__isnull'.format(self.field_name): True})
)


class PythonPolygonFilter(PolygonFilter):

Expand Down
8 changes: 4 additions & 4 deletions mapentity/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import bs4
import requests
from django.conf import settings
from django.contrib.gis.gdal.error import OGRException
from django.contrib.gis.gdal.error import GDALException
from django.contrib.gis.geos import GEOSException, fromstr
from django.urls import resolve
from django.http import HttpResponse
Expand Down Expand Up @@ -86,7 +86,7 @@ def wkt_to_geom(wkt, srid_from=None, silent=False):
srid_from = API_SRID
try:
return fromstr(wkt, srid=srid_from)
except (OGRException, GEOSException) as e:
except (GDALException, GEOSException) as e:
if not silent:
raise e
return None
Expand All @@ -108,7 +108,7 @@ def transform_wkt(wkt, srid_from=None, srid_to=None, dim=3):
wkt3d = geom.wkt.replace(',', extracoords + ',')
wkt3d = wkt3d.replace(')', extracoords + ')')
return 'SRID=%s;%s' % (srid_to, wkt3d)
except (OGRException, GEOSException, TypeError, ValueError) as e:
except (GDALException, GEOSException, TypeError, ValueError) as e:
if settings.DEBUG or not getattr(settings, 'TEST', False):
logger.error("wkt_to_geom('%s', %s, %s) : %s" % (wkt, srid_from, srid_to, e))
return None
Expand Down Expand Up @@ -311,7 +311,7 @@ def user_has_perm(user, perm):
# First check if the user has the permission (even anon user)
if user.has_perm(perm):
return True
if user.is_anonymous():
if user.is_anonymous:
return perm in app_settings['ANONYMOUS_VIEWS_PERMS']
return False

Expand Down
12 changes: 8 additions & 4 deletions mapentity/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,17 @@ def clear_internal_user_cache():
del get_internal_user.instance


class AutoLoginMiddleware(object):
class AutoLoginMiddleware:
"""
This middleware enables auto-login for Conversion and Capture servers.
We could have deployed implemented authentication in ConvertIt and
django-screamshot, or deployed OpenId, or whatever. But this was a lot easier.
"""
def process_request(self, request):
def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
if "HTTP_X_FORWARDED_FOR" in request.META:
request.META["HTTP_X_PROXY_REMOTE_ADDR"] = request.META["REMOTE_ADDR"]
parts = request.META["HTTP_X_FORWARDED_FOR"].split(",", 1)
Expand All @@ -57,7 +60,7 @@ def process_request(self, request):
getattr(settings, 'TEST', False))

user = getattr(request, 'user', None)
if user and user.is_anonymous() and not is_running_tests:
if user and user.is_anonymous and not is_running_tests:
remoteip = request.META.get('REMOTE_ADDR')
remotehost = request.META.get('REMOTE_HOST')

Expand All @@ -75,4 +78,5 @@ def process_request(self, request):
except DatabaseError:
logger.error("Could not update last-login field of internal user")
request.user = user
return None

return self.get_response(request)
File renamed without changes.
File renamed without changes.
File renamed without changes.
39 changes: 17 additions & 22 deletions mapentity/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from io import StringIO
from unittest.mock import patch

import requests
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase, LiveServerTestCase
Expand Down Expand Up @@ -324,7 +323,6 @@ class MapEntityLiveTest(LiveServerTestCase):
model = None
userfactory = None
modelfactory = None
session = None

def _pre_setup(self):
# Workaround https://code.djangoproject.com/ticket/10827
Expand All @@ -336,16 +334,15 @@ def url_for(self, path):

def login(self):
user = self.userfactory(password='booh')
self.session = requests.Session()
login_url = self.url_for('/login/')
response = self.session.get(login_url,
allow_redirects=False)
response = self.client.get(login_url,
allow_redirects=False)
csrftoken = response.cookies['csrftoken']
response = self.session.post(login_url,
{'username': user.username,
'password': 'booh',
'csrfmiddlewaretoken': csrftoken},
allow_redirects=False)
response = self.client.post(login_url,
{'username': user.username,
'password': 'booh',
'csrfmiddlewaretoken': csrftoken},
allow_redirects=False)
self.assertEqual(response.status_code, 302)

@patch('mapentity.models.MapEntityMixin.latest_updated')
Expand All @@ -360,12 +357,12 @@ def test_geojson_cache(self, latest_updated):
latest = self.model.latest_updated()
geojson_layer_url = self.url_for(self.model.get_layer_url())

response = self.session.get(geojson_layer_url, allow_redirects=False)
response = self.client.get(geojson_layer_url, allow_redirects=False)
self.assertEqual(response.status_code, 200)

# Without headers to cache
lastmodified = response.headers.get('Last-Modified')
cachecontrol = response.headers.get('Cache-control')
lastmodified = response.get('Last-Modified')
cachecontrol = response.get('Cache-control')
hasher = hashlib.md5()
hasher.update(response.content)
md5sum = hasher.digest()
Expand All @@ -375,8 +372,8 @@ def test_geojson_cache(self, latest_updated):
# Try again, check that nothing changed
time.sleep(1.1)
self.assertEqual(latest, self.model.latest_updated())
response = self.session.get(geojson_layer_url)
self.assertEqual(lastmodified, response.headers.get('Last-Modified'))
response = self.client.get(geojson_layer_url)
self.assertEqual(lastmodified, response.get('Last-Modified'))
new_hasher = hashlib.md5()
new_hasher.update(response.content)
self.assertEqual(md5sum, new_hasher.digest())
Expand All @@ -387,22 +384,20 @@ def test_geojson_cache(self, latest_updated):
latest_updated.return_value = datetime.utcnow().replace(tzinfo=utc)

self.assertNotEqual(latest, self.model.latest_updated())
response = self.session.get(geojson_layer_url)
response = self.client.get(geojson_layer_url)
# Check that last modified and content changed
self.assertNotEqual(lastmodified, response.headers.get('Last-Modified'))
self.assertNotEqual(lastmodified, response.get('Last-Modified'))
new_hasher = hashlib.md5()
new_hasher.update(response.content)
self.assertNotEqual(md5sum, new_hasher.digest())

# Ask again with headers, and expect a 304 status (not changed)
lastmodified = response.headers.get('Last-Modified')
response = self.session.get(geojson_layer_url,
headers={'if-modified-since': lastmodified})
lastmodified = response.get('Last-Modified')
response = self.client.get(geojson_layer_url, HTTP_IF_MODIFIED_SINCE=lastmodified)
self.assertEqual(response.status_code, 304)

# Ask again with headers in the past, and expect a 200
response = self.session.get(geojson_layer_url,
headers={'if-modified-since': http_date(1000)})
response = self.client.get(geojson_layer_url, HTTP_IF_MODIFIED_SINCE=http_date(1000))
self.assertEqual(response.status_code, 200)
new_hasher = hashlib.md5()
new_hasher.update(response.content)
Expand Down
16 changes: 8 additions & 8 deletions mapentity/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.conf import settings
from django.conf.urls import url, include
from django.urls import path, re_path, include

from .settings import app_settings
from .registry import registry
Expand All @@ -16,21 +16,21 @@
_MEDIA_URL = _MEDIA_URL[:-1]


app_name = 'mapentity'
urlpatterns = [
url(r'^map_screenshot/$', map_screenshot, name='map_screenshot'),
url(r'^convert/$', Convert.as_view(), name='convert'),
url(r'^history/delete/$', history_delete, name='history_delete'),
url(r'^api/auth/', include('rest_framework.urls', namespace='rest_framework')),
path('map_screenshot/', map_screenshot, name='map_screenshot'),
path('convert/', Convert.as_view(), name='convert'),
path('history/delete/', history_delete, name='history_delete'),
path('api/auth/', include('rest_framework.urls')),
# See default value in app_settings.JS_SETTINGS.
# Will be overriden, most probably.
url(r'^api/settings.json$', JSSettings.as_view(), name='js_settings'),
path('api/settings.json', JSSettings.as_view(), name='js_settings'),
]


if settings.DEBUG or app_settings['SENDFILE_HTTP_HEADER']:
urlpatterns += [
url(r'^%s/(?P<path>paperclip/.*)$' % _MEDIA_URL,
serve_attachment),
re_path(r'^%s/(?P<path>paperclip/.*)$' % _MEDIA_URL, serve_attachment),
]


Expand Down
5 changes: 0 additions & 5 deletions mapentity/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
ModelViewMixin,
)
from .base import (
handler403,
handler404,
serve_attachment,
JSSettings,
map_screenshot,
Expand Down Expand Up @@ -76,9 +74,6 @@
'ModelViewMixin',
'MAPENTITY_GENERIC_VIEWS',

'handler403',
'handler404',
'handler500',
'serve_attachment',
'JSSettings',
'map_screenshot',
Expand Down
11 changes: 1 addition & 10 deletions mapentity/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from django.views import static
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.views.defaults import page_not_found, permission_denied
from django.views.generic.base import TemplateView
from paperclip.settings import get_attachment_permission, get_attachment_model

Expand All @@ -31,14 +30,6 @@
logger = logging.getLogger(__name__)


def handler403(request, template_name='mapentity/403.html'):
return permission_denied(request, template_name)


def handler404(request, template_name='mapentity/404.html'):
return page_not_found(request, template_name)


def serve_attachment(request, path):
"""
Serve media/ for authorized users only, since it can contain sensitive
Expand All @@ -50,7 +41,7 @@ def serve_attachment(request, path):
if not issubclass(obj._meta.model, mapentity_models.MapEntityMixin):
raise Http404
if not obj.is_public():
if not request.user.is_authenticated():
if not request.user.is_authenticated:
raise PermissionDenied
if not request.user.has_perm(get_attachment_permission('read_attachment')):
raise PermissionDenied
Expand Down
Loading

0 comments on commit a3661ec

Please sign in to comment.