Попросили рассказать про этот пакет, чем я и займусь.
Для чего нужен пакет
Django позволяет хранить и отображать географические поля. Если вы откроете админку объекта, в котором есть географическое поле, вы увидите участок карты с размещенными на ней геометрическими деталями - точкой, линией, полигоном или даже все это вместе, в зависимости от типа поля.

Однако, открыв стандартный список объектов в админке, вы не увидите их географического отображения. Их относительное расположение, группировка по географическим пунктам и прочие детали их географии, остаются для вас нераскрытыми, пока вы не заглянули на отдельную страницу редактирования объекта.
Чтобы исправить этот недостаток, был придуман пакет django-leaflet-admin-list. Он отображает все объекты из страницы списка на общей карте, размещенной сверху списка.

Теперь взаимное расположение двух зданий на карте вполне очевидно сразу при просмотре списка зданий, без необходимости открывать каждый объект и смотреть их по отдельности.
Если у модели есть несколько геополей, они все отображаются на карте совместно, что также улучшает пользовательский опыт.
Как пользоваться
Пакет устанавливается из хранилища PyPi. После установки, включите пакет (рекомендую также использовать пакет django-leaflet для сохранения единого визуального стиля, хотя это не обязательно) в список используемых пакетов в файле settings.py
, как это обычно делается для проекта Django:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
...
'leaflet',
'leaflet_admin_list',
...
]
Используйте LeafletAdminListMixin
в качестве одного из базовых классов для админки вашей географической модели:
...
from leaflet_admin_list.admin import LeafletAdminListMixin
...
class BuildingAdmin(LeafletAdminListMixin, ModelAdmin):
...
Админка модели может использовать пакет django-leaflet одновременно с пакетом django-leaflet-admin-list:
...
from leaflet.admin import LeafletGeoAdminMixin
from leaflet_admin_list.admin import LeafletAdminListMixin
...
class BuildingAdmin(LeafletAdminListMixin, LeafletGeoAdminMixin, ModelAdmin):
...
Теперь список объектов модели Building
в админке будет отображаться с картой, на которой будут отображены все объекты, попавшие на страницу.
Кастомизация объектов на карте
Объекты на карте отображаются с помощью GeoJSON, загружаемого прямо на страницу при ее рендеринге, в виде части кода JavaScript. Содержимое отображаемого GeoJSON формируется методом миксина get_geojson_feature_list
. Тот, в свою очередь, вызывает другие методы миксина, каждый из которых можно перекрыть собственной реализацией. Стек вызовов методов выглядит следующим образом:
-
get_geojson_feature_list
-
get_geojson_features
get_geojson_geometry_fields
-
get_geojson_feature
get_geojson_geometry
-
get_geojson_properties
get_geojson_feature_popup
-
get_geojson_feature_tooltip
get_geojson_feature_verbose_name
-
get_geojson_feature_point_style
get_geojson_feature_icon_style
get_geojson_feature_line_style
-
Финальный формат возвращаемого объекта полностью соответствует стандартному GeoJSON, который используется в вызове конструктора L.GeoJSON библиотеки LeafletJS. Все свойства передаются через атрибут properties
соответствующих географических объектов GeoJSON и обрабатываются кодом JavaScript, превращаясь в соответствующие графические элементы с помощью обратных вызовов.
Посмотрим, как мы можем изменить отображение географических объектов.
Попробуем согласно документации LeafletJS, изменить цвет линий и заполнения на ярко-зеленый и темно-зеленый соответственно. Обратите внимание, что я сделал фон полностью непрозрачным, чтобы цвет был виден лучше.
class BuildingAdmin(LeafletAdminListMixin, LeafletGeoAdminMixin, ModelAdmin):
...
def get_geojson_feature_line_style(self, request, name, o, queryset):
return {
'color': '#00F000',
'fillColor': '#00A000',
'fillOpacity': 1.0,
}

Теперь исправим иконки, обозначающие подъезды у зданий. Сделаем их крохотными кружочками, центрированными по координатам точек
class BuildingAdmin(LeafletAdminListMixin, LeafletGeoAdminMixin, ModelAdmin):
...
def get_geojson_feature_line_style(self, request, name, o, queryset):
return {
'color': '#00F000',
'fillColor': '#00A000',
'fillOpacity': 1.0,
}
def get_geojson_feature_icon_style(self, request, name, o, queryset):
return {
'iconUrl': 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyBpZD0iTGF5ZXJfMV8xXyIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTYgMTY7IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g
'iconSize': [5, 5],
'iconAnchor': [3, 3]
}
И посмотрим на результат.

Тем же способом, вы можете кастомизировать все аспекты отображения ваших географических объектов, вплоть до того, чтобы самому сгенерировать GeoJSON полностью.
Перекрывая методы, вы можете полностью контролировать вывод объектов на карту, в зависимости от параметров вызовов:
request
- запрос HTTPqueryset
- список объектов модели, подлежащих выводу в соответствие с параметрами постраничной разбивкиo
- объект моделиname
- имя поля
Например, вы можете:
добавлять свои объекты на карту (допустим, вы хотели бы отображать текущее местоположение пользователя)
игнорировать отдельные объекты, не выводя их на карту (например, желая скрыть географическую информацию о них)
анализировать негеографические поля объекта и применять разные стили в зависимости от них (например, менять цвет линий и фона многоугольников в зависимости от типа или статуса объекта, использовать разные иконки для точек и т.д.)
анализировать, какое именно поле выводится, чтобы выводить разные поля разными стилями (например, выделяя конструктивные элементы объекта, прилежащую территорию, и т.п.)
Заключение
Использование пакета регулируется лицензией открытого кода LGPL. Поделитесь здесь своим опытом использования пакета, присоединяйтесь к его разработке на GitHub, предлагая новые свойства и готовые исправления для общей пользы.