options.py 6.24 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
import warnings

from django.contrib.admin import ModelAdmin
from django.contrib.gis.admin.widgets import OpenLayersWidget
from django.contrib.gis.db import models
from django.contrib.gis.forms import OSMWidget
from django.contrib.gis.gdal import OGRGeomType
from django.forms import Media
from django.utils.deprecation import RemovedInDjango50Warning


class GeoModelAdminMixin:
    gis_widget = OSMWidget
    gis_widget_kwargs = {}

    def formfield_for_dbfield(self, db_field, request, **kwargs):
        if isinstance(db_field, models.GeometryField) and (
            db_field.dim < 3 or self.gis_widget.supports_3d
        ):
            kwargs["widget"] = self.gis_widget(**self.gis_widget_kwargs)
            return db_field.formfield(**kwargs)
        else:
            return super().formfield_for_dbfield(db_field, request, **kwargs)


class GISModelAdmin(GeoModelAdminMixin, ModelAdmin):
    pass


# RemovedInDjango50Warning.
spherical_mercator_srid = 3857


# RemovedInDjango50Warning.
class GeoModelAdmin(ModelAdmin):
    """
    The administration options class for Geographic models. Map settings
    may be overloaded from their defaults to create custom maps.
    """

    # The default map settings that may be overloaded -- still subject
    # to API changes.
    default_lon = 0
    default_lat = 0
    default_zoom = 4
    display_wkt = False
    display_srid = False
    extra_js = []
    num_zoom = 18
    max_zoom = False
    min_zoom = False
    units = False
    max_resolution = False
    max_extent = False
    modifiable = True
    mouse_position = True
    scale_text = True
    layerswitcher = True
    scrollable = True
    map_width = 600
    map_height = 400
    map_srid = 4326
    map_template = "gis/admin/openlayers.html"
    openlayers_url = (
        "https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.13.1/OpenLayers.js"
    )
    point_zoom = num_zoom - 6
    wms_url = "http://vmap0.tiles.osgeo.org/wms/vmap0"
    wms_layer = "basic"
    wms_name = "OpenLayers WMS"
    wms_options = {"format": "image/jpeg"}
    debug = False
    widget = OpenLayersWidget

    def __init__(self, *args, **kwargs):
        warnings.warn(
            "django.contrib.gis.admin.GeoModelAdmin and OSMGeoAdmin are "
            "deprecated in favor of django.contrib.admin.ModelAdmin and "
            "django.contrib.gis.admin.GISModelAdmin.",
            RemovedInDjango50Warning,
            stacklevel=2,
        )
        super().__init__(*args, **kwargs)

    @property
    def media(self):
        "Injects OpenLayers JavaScript into the admin."
        return super().media + Media(js=[self.openlayers_url] + self.extra_js)

    def formfield_for_dbfield(self, db_field, request, **kwargs):
        """
        Overloaded from ModelAdmin so that an OpenLayersWidget is used
        for viewing/editing 2D GeometryFields (OpenLayers 2 does not support
        3D editing).
        """
        if isinstance(db_field, models.GeometryField) and db_field.dim < 3:
            # Setting the widget with the newly defined widget.
            kwargs["widget"] = self.get_map_widget(db_field)
            return db_field.formfield(**kwargs)
        else:
            return super().formfield_for_dbfield(db_field, request, **kwargs)

    def get_map_widget(self, db_field):
        """
        Return a subclass of the OpenLayersWidget (or whatever was specified
        in the `widget` attribute) using the settings from the attributes set
        in this class.
        """
        is_collection = db_field.geom_type in (
            "MULTIPOINT",
            "MULTILINESTRING",
            "MULTIPOLYGON",
            "GEOMETRYCOLLECTION",
        )
        if is_collection:
            if db_field.geom_type == "GEOMETRYCOLLECTION":
                collection_type = "Any"
            else:
                collection_type = OGRGeomType(db_field.geom_type.replace("MULTI", ""))
        else:
            collection_type = "None"

        class OLMap(self.widget):
            template_name = self.map_template
            geom_type = db_field.geom_type

            wms_options = ""
            if self.wms_options:
                wms_options = ["%s: '%s'" % pair for pair in self.wms_options.items()]
                wms_options = ", %s" % ", ".join(wms_options)

            params = {
                "default_lon": self.default_lon,
                "default_lat": self.default_lat,
                "default_zoom": self.default_zoom,
                "display_wkt": self.debug or self.display_wkt,
                "geom_type": OGRGeomType(db_field.geom_type),
                "field_name": db_field.name,
                "is_collection": is_collection,
                "scrollable": self.scrollable,
                "layerswitcher": self.layerswitcher,
                "collection_type": collection_type,
                "is_generic": db_field.geom_type == "GEOMETRY",
                "is_linestring": db_field.geom_type
                in ("LINESTRING", "MULTILINESTRING"),
                "is_polygon": db_field.geom_type in ("POLYGON", "MULTIPOLYGON"),
                "is_point": db_field.geom_type in ("POINT", "MULTIPOINT"),
                "num_zoom": self.num_zoom,
                "max_zoom": self.max_zoom,
                "min_zoom": self.min_zoom,
                "units": self.units,  # likely should get from object
                "max_resolution": self.max_resolution,
                "max_extent": self.max_extent,
                "modifiable": self.modifiable,
                "mouse_position": self.mouse_position,
                "scale_text": self.scale_text,
                "map_width": self.map_width,
                "map_height": self.map_height,
                "point_zoom": self.point_zoom,
                "srid": self.map_srid,
                "display_srid": self.display_srid,
                "wms_url": self.wms_url,
                "wms_layer": self.wms_layer,
                "wms_name": self.wms_name,
                "wms_options": wms_options,
                "debug": self.debug,
            }

        return OLMap


# RemovedInDjango50Warning.
class OSMGeoAdmin(GeoModelAdmin):
    map_template = "gis/admin/osm.html"
    num_zoom = 20
    map_srid = spherical_mercator_srid
    max_extent = "-20037508,-20037508,20037508,20037508"
    max_resolution = "156543.0339"
    point_zoom = num_zoom - 6
    units = "m"