Skip to content

Commit

Permalink
Merge pull request #231 from makinacorpus/paginate_list_geotrek_integ…
Browse files Browse the repository at this point in the history
…ration

Paginate list geotrek integration
  • Loading branch information
submarcos authored Apr 13, 2022
2 parents 975caf9 + 084abaa commit 5508f00
Show file tree
Hide file tree
Showing 91 changed files with 1,575 additions and 30,902 deletions.
455 changes: 235 additions & 220 deletions CHANGES → CHANGES.md

Large diffs are not rendered by default.

15 changes: 9 additions & 6 deletions docs/customization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ can override CBV methods as usual::

from django.shortcuts import redirect
from mapentity.views.generic import (
MapEntityList, MapEntityLayer, MapEntityJsonList, MapEntityDetail,
MapEntityList, MapEntityLayer, MapEntityDetail,
MapEntityFormat, MapEntityCreate, MapEntityUpdate, MapEntityDocument,
MapEntityDelete)
MapEntityDelete, MapEntityViewSet)
from .models import Museum
from .serializers import MuseumSerializer


def home(request):
Expand All @@ -29,10 +30,6 @@ can override CBV methods as usual::
model = Museum


class MuseumJsonList(MapEntityJsonList, MuseumList):
pass


class MuseumDetail(MapEntityDetail):
model = Museum

Expand All @@ -57,6 +54,12 @@ can override CBV methods as usual::
model = Museum


class MuseumViewSet(MapEntityViewSet):
model = Museum
serializer_class = MuseumSerializer



Filters
-------

Expand Down
2 changes: 1 addition & 1 deletion mapentity/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.1.3+dev
8.0.0
7 changes: 6 additions & 1 deletion mapentity/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Make sure mapentity settings are loaded before leaflet ones
import os
from . import settings # noqa

here = os.path.abspath(os.path.dirname(__file__))

with open(os.path.join(here, 'VERSION')) as version_file:
VERSION = version_file.read().strip()

default_app_config = 'mapentity.apps.MapEntityConfig'
__version__ = '6.1.1.dev0'
__version__ = VERSION
31 changes: 25 additions & 6 deletions mapentity/filters.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from django.conf import settings
from django.contrib.gis import forms
from django.contrib.gis.geos import Polygon
from django.db.models.fields.related import ManyToOneRel, ForeignKey
from django_filters import FilterSet, Filter, ModelMultipleChoiceFilter
from django_filters import ModelMultipleChoiceFilter, Filter
from django_filters.filterset import get_model_field, remote_queryset
from django_filters.rest_framework import FilterSet

from .settings import app_settings, API_SRID
from .widgets import HiddenGeometryWidget
from mapentity.settings import app_settings, API_SRID
from mapentity.widgets import HiddenGeometryWidget


class PolygonFilter(Filter):

field_class = forms.PolygonField

def __init__(self, *args, **kwargs):
Expand All @@ -18,10 +19,27 @@ def __init__(self, *args, **kwargs):
kwargs.setdefault('lookup_expr', 'intersects')
super().__init__(*args, **kwargs)

def get_value_with_bounds_fixed(self, value):
if value:
# prevent bbox out of bounding (leaflet getBounds)
xmin, ymin, xmax, ymax = value.extent
xmin = max(xmin, -180)
xmax = min(xmax, 180)
ymin = max(ymin, -90)
ymax = min(ymax, 90)
new_bbox = Polygon.from_bbox((xmin, ymin, xmax, ymax))
new_bbox.srid = value.srid
return new_bbox
return value

class PythonPolygonFilter(PolygonFilter):
def filter(self, qs, value):
value = self.get_value_with_bounds_fixed(value)
return super().filter(qs, value)


class PythonPolygonFilter(PolygonFilter):
def filter(self, qs, value):
value = self.get_value_with_bounds_fixed(value)
if not value:
return qs
if not value.srid:
Expand Down Expand Up @@ -57,7 +75,8 @@ def __bypass_labels(self):
elif isinstance(field, forms.ChoiceField):
self.__set_placeholder(field, field.widget)
elif isinstance(field, forms.NullBooleanField):
choices = [('1', field.label)] + field.widget.choices[1:]
# use label as undefined value for NullBooleanField
choices = [(None, field.label)] + field.widget.choices[1:]
field.widget.choices = choices
self.__set_placeholder(field, field.widget)
else:
Expand Down
14 changes: 6 additions & 8 deletions mapentity/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
# Used to create the matching url name
ENTITY_LAYER = "layer"
ENTITY_LIST = "list"
ENTITY_JSON_LIST = "json_list"
ENTITY_DATATABLE_LIST = "-drf-list"
ENTITY_FORMAT_LIST = "format_list"
ENTITY_DETAIL = "detail"
ENTITY_MAPIMAGE = "mapimage"
Expand All @@ -36,9 +36,8 @@
ENTITY_UPDATE_GEOM = "update_geom"

ENTITY_KINDS = (
ENTITY_LAYER, ENTITY_LIST, ENTITY_JSON_LIST,
ENTITY_FORMAT_LIST, ENTITY_DETAIL, ENTITY_MAPIMAGE, ENTITY_DOCUMENT, ENTITY_MARKUP, ENTITY_CREATE,
ENTITY_UPDATE, ENTITY_DELETE, ENTITY_UPDATE_GEOM
ENTITY_LAYER, ENTITY_LIST, ENTITY_DATATABLE_LIST, ENTITY_FORMAT_LIST, ENTITY_DETAIL, ENTITY_MAPIMAGE,
ENTITY_DOCUMENT, ENTITY_MARKUP, ENTITY_CREATE, ENTITY_UPDATE, ENTITY_DELETE, ENTITY_UPDATE_GEOM
)

ENTITY_PERMISSION_CREATE = 'add'
Expand Down Expand Up @@ -95,9 +94,8 @@ def get_entity_kind_permission(cls, entity_kind):
ENTITY_DETAIL: ENTITY_PERMISSION_READ,
ENTITY_LAYER: ENTITY_PERMISSION_READ,
ENTITY_LIST: ENTITY_PERMISSION_READ,
ENTITY_JSON_LIST: ENTITY_PERMISSION_READ,
ENTITY_DATATABLE_LIST: ENTITY_PERMISSION_READ,
ENTITY_MARKUP: ENTITY_PERMISSION_READ,

ENTITY_FORMAT_LIST: ENTITY_PERMISSION_EXPORT,
ENTITY_MAPIMAGE: ENTITY_PERMISSION_EXPORT,
ENTITY_DOCUMENT: ENTITY_PERMISSION_EXPORT,
Expand Down Expand Up @@ -152,8 +150,8 @@ def get_list_url(cls):
return reverse(cls._entity.url_name(ENTITY_LIST))

@classmethod
def get_jsonlist_url(cls):
return reverse(cls._entity.url_name(ENTITY_JSON_LIST))
def get_datatablelist_url(cls):
return reverse(f"{cls._meta.app_label}:{cls._meta.model_name}-drf-list") + ".datatables"

@classmethod
def get_format_list_url(cls):
Expand Down
11 changes: 11 additions & 0 deletions mapentity/pagination.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from rest_framework_datatables.pagination import DatatablesPageNumberPagination


class MapentityDatatablePagination(DatatablesPageNumberPagination):
""" Custom datatable pagination for Mapentity list views. """

def get_count_and_total_count(self, queryset, view):
""" Handle count for all filters """
count, total_count = super().get_count_and_total_count(queryset, view)
count = queryset.count() # replace count by real count - not only drf-datatables count
return count, total_count
16 changes: 8 additions & 8 deletions mapentity/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
from django.contrib.contenttypes.models import ContentType
from django.db import DEFAULT_DB_ALIAS
from django.db.utils import ProgrammingError
from django.urls import re_path, include
from django.urls import re_path, include, path
from django.utils.translation import gettext as _
from django.views.generic.base import View
from paperclip.settings import get_attachment_model
from rest_framework import routers as rest_routers
from rest_framework import serializers as rest_serializers
from rest_framework.serializers import ModelSerializer
from rest_framework_gis.fields import GeometryField
from rest_framework_gis.serializers import GeoFeatureModelSerializer

Expand Down Expand Up @@ -95,8 +95,7 @@ def scan_views(self):
for generic_view in generic_views:
already_defined = any([issubclass(view, generic_view) for view in picked])
if not already_defined:
list_dependencies = (mapentity_views.MapEntityJsonList,
mapentity_views.MapEntityFormat)
list_dependencies = (mapentity_views.MapEntityFormat, )
if list_view and generic_view in list_dependencies:
# List view depends on JsonList and Format view
class dynamic_view(generic_view, list_view):
Expand All @@ -119,15 +118,16 @@ class dynamic_viewset(mapentity_views.MapEntityViewSet):
geojson_serializer_class = _geojson_serializer
rest_viewset = dynamic_viewset

self.rest_router.register(self.modelname + 's', rest_viewset, basename=self.modelname)
self.rest_router.register(r'api/' + self.modelname + '/drf/' + self.modelname + 's',
rest_viewset, basename=f"{self.modelname}-drf")

# Returns Django URL patterns
return self.__view_classes_to_url(*picked)

def get_serializer(self):
_model = self.model

class Serializer(rest_serializers.ModelSerializer):
class Serializer(ModelSerializer):
class Meta:
model = _model
id_field = 'id'
Expand Down Expand Up @@ -156,7 +156,7 @@ def _url_path(self, view_kind):
kind_to_urlpath = {
mapentity_models.ENTITY_LAYER: r'^api/{modelname}/{modelname}.geojson$',
mapentity_models.ENTITY_LIST: r'^{modelname}/list/$',
mapentity_models.ENTITY_JSON_LIST: r'^api/{modelname}/{modelname}s.json$',
mapentity_models.ENTITY_DATATABLE_LIST: r'^api/{modelname}/drf/{modelname}s.datatable$',
mapentity_models.ENTITY_FORMAT_LIST: r'^{modelname}/list/export/$',
mapentity_models.ENTITY_DETAIL: r'^{modelname}/(?P<pk>\d+)/$',
mapentity_models.ENTITY_MAPIMAGE: r'^image/{modelname}-(?P<pk>\d+).png$',
Expand All @@ -181,7 +181,7 @@ def url_for(self, view_class):

def __view_classes_to_url(self, *view_classes):
return [self.url_for(view_class) for view_class in view_classes] + \
[re_path(app_settings['DRF_API_URL_PREFIX'], include(self.rest_router.urls))]
[path('', include(self.rest_router.urls))]

def url_shortname(self, kind):
assert kind in mapentity_models.ENTITY_KINDS
Expand Down
4 changes: 2 additions & 2 deletions mapentity/serializers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .commasv import CSVSerializer
from .datatables import DatatablesSerializer
from .datatables import MapentityDatatableSerializer
from .gpx import GPXSerializer
from .helpers import json_django_dumps, plain_text, smart_plain_text
from .shapefile import ZipShapeSerializer
Expand All @@ -8,6 +8,6 @@
'smart_plain_text',
'CSVSerializer',
'GPXSerializer',
'DatatablesSerializer',
'MapentityDatatableSerializer',
'ZipShapeSerializer',
'json_django_dumps']
53 changes: 14 additions & 39 deletions mapentity/serializers/datatables.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,17 @@
import math
from django.db import models
from rest_framework.serializers import ModelSerializer

from django.core.serializers.base import Serializer
from django.db.models.fields.related import ForeignKey, ManyToManyField
from django.utils.translation import gettext_lazy as _
from mapentity.serializers import fields


class DatatablesSerializer(Serializer):
def serialize(self, queryset, **options):
model = options.pop('model', None) or queryset.model
columns = options.pop('fields')

getters = {}
for field in columns:
if hasattr(model, field + '_display'):
getters[field] = lambda obj, field: getattr(obj, field + '_display')
else:
modelfield = model._meta.get_field(field)
if isinstance(modelfield, ForeignKey):
getters[field] = lambda obj, field: (getattr(obj, field) or _("None"))
elif isinstance(modelfield, ManyToManyField):
getters[field] = lambda obj, field: (getattr(obj, field).all() or _("None"))
else:
def fixfloat(obj, field):
value = getattr(obj, field)
if isinstance(value, float) and math.isnan(value):
value = 0.0
return value
getters[field] = fixfloat
# Build list with fields
map_obj_pk = []
data_table_rows = []
for obj in queryset:
row = [getters[field](obj, field) for field in columns]
data_table_rows.append(row)
map_obj_pk.append(obj.pk)

return {
# aaData is the key looked up by dataTables
'aaData': data_table_rows,
'map_obj_pk': map_obj_pk,
}
class MapentityDatatableSerializer(ModelSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# patch mapping fields to use datatables format
mappings = self.serializer_field_mapping.copy()
mappings.update({
models.BooleanField: fields.MapentityDatatableBooleanField,
models.DateTimeField: fields.MapentityDatatableDateTimeField,
models.DateField: fields.MapentityDatatableDateField,
})
self.serializer_field_mapping = mappings
26 changes: 26 additions & 0 deletions mapentity/serializers/fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from rest_framework import serializers


class MapentityDatatableDateTimeField(serializers.DateTimeField):
def __init__(self, *args, **kwargs):
""" Set default format """
kwargs.update({'format': "%d/%m/%Y %H:%M:%S"})
super().__init__(*args, **kwargs)


class MapentityDatatableDateField(serializers.DateField):
def __init__(self, *args, **kwargs):
""" Set default format """
kwargs.update({'format': "%d/%m/%Y"})
super().__init__(*args, **kwargs)


class MapentityDatatableBooleanField(serializers.BooleanField):
""" Set default format """
def to_representation(self, value):
if value:
return '<i class="bi bi-check-circle text-success"></i>'
elif value is False:
return '<i class="bi bi-x-circle text-danger"></i>'
else:
return '<i class="bi bi-question-circle"></i>'
51 changes: 0 additions & 51 deletions mapentity/static/mapentity/dataTables/css/dataTables.bootstrap.css

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit 5508f00

Please sign in to comment.