Skip to content

📘 API Reference WebGIS

Georama WebGIS

admin

LayerGroupMpAdmin

Bases: TreeAdmin

Source code in src/georama/webgis/admin.py
73
74
75
76
77
78
79
class LayerGroupMpAdmin(TreeAdmin):
    form = movenodeform_factory(models.LayerGroupMp)
    list_display = ("name",)

    def move_node(self, request, extra_context=None):
        # Call the original method without the extra_context
        return super().move_node(request)

form = movenodeform_factory(models.LayerGroupMp) class-attribute instance-attribute

list_display = ('name') class-attribute instance-attribute

move_node(request, extra_context=None)

Source code in src/georama/webgis/admin.py
77
78
79
def move_node(self, request, extra_context=None):
    # Call the original method without the extra_context
    return super().move_node(request)

LayerWmsAdmin

Bases: ModelAdmin

Source code in src/georama/webgis/admin.py
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
class LayerWmsAdmin(admin.ModelAdmin):
    list_display = ["name", "title", "public"]
    list_editable = ["public"]

    def get_urls(self):
        urls = super().get_urls()
        my_urls = [
            path(
                "datasets/",
                self.admin_site.admin_view(self.datasets),
                name="datasets",
            )
        ]
        return my_urls + urls

    def datasets(self, request: HttpRequest, extra_context=None):
        extra_context = extra_context or {}
        extra_context.update(
            dict(
                # Include common variables for rendering the admin template.
                self.admin_site.each_context(request),
                # Anything else you want in the context...
                raster_datasets=RasterDataSet.objects.all(),
                vector_datasets=VectorDataSet.objects.all(),
                custom_datasets=CustomDataSet.objects.all(),
                publish_dataset_as_wms_view_name="webgis_publish_dataset_as_wms",
            )
        )
        return TemplateResponse(
            request, "admin/maps/publishedaswms/publish.html", extra_context
        )

    def changelist_view(self, request, extra_context=None):
        extra_context = extra_context or {}
        extra_context[
            "wms_get_capabilities_url"
        ] = "{}?SERVICE=WMS&REQUEST=GETCAPABILITIES&VERSION=1.3.0".format(
            reverse("webgis_ogc_entry")
        )
        extra_context[
            "wfs_get_capabilities_url"
        ] = "{}?SERVICE=WFS&REQUEST=GETCAPABILITIES&VERSION=2.0.0".format(
            reverse("webgis_ogc_entry")
        )
        return super().changelist_view(
            request,
            extra_context=extra_context,
        )

list_display = ['name', 'title', 'public'] class-attribute instance-attribute

list_editable = ['public'] class-attribute instance-attribute

changelist_view(request, extra_context=None)

Source code in src/georama/webgis/admin.py
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
def changelist_view(self, request, extra_context=None):
    extra_context = extra_context or {}
    extra_context[
        "wms_get_capabilities_url"
    ] = "{}?SERVICE=WMS&REQUEST=GETCAPABILITIES&VERSION=1.3.0".format(
        reverse("webgis_ogc_entry")
    )
    extra_context[
        "wfs_get_capabilities_url"
    ] = "{}?SERVICE=WFS&REQUEST=GETCAPABILITIES&VERSION=2.0.0".format(
        reverse("webgis_ogc_entry")
    )
    return super().changelist_view(
        request,
        extra_context=extra_context,
    )

datasets(request, extra_context=None)

Source code in src/georama/webgis/admin.py
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
def datasets(self, request: HttpRequest, extra_context=None):
    extra_context = extra_context or {}
    extra_context.update(
        dict(
            # Include common variables for rendering the admin template.
            self.admin_site.each_context(request),
            # Anything else you want in the context...
            raster_datasets=RasterDataSet.objects.all(),
            vector_datasets=VectorDataSet.objects.all(),
            custom_datasets=CustomDataSet.objects.all(),
            publish_dataset_as_wms_view_name="webgis_publish_dataset_as_wms",
        )
    )
    return TemplateResponse(
        request, "admin/maps/publishedaswms/publish.html", extra_context
    )

get_urls()

Source code in src/georama/webgis/admin.py
23
24
25
26
27
28
29
30
31
32
def get_urls(self):
    urls = super().get_urls()
    my_urls = [
        path(
            "datasets/",
            self.admin_site.admin_view(self.datasets),
            name="datasets",
        )
    ]
    return my_urls + urls

LayerWmtsAdmin

Bases: ModelAdmin

Source code in src/georama/webgis/admin.py
69
70
class LayerWmtsAdmin(admin.ModelAdmin):
    pass

LayergroupmpInlines

Bases: TabularInline

Source code in src/georama/webgis/admin.py
82
83
84
85
86
class LayergroupmpInlines(admin.TabularInline):
    model = models.LayerGroupMp
    extra = 2
    verbose_name = _("Groupe de couche")
    verbose_name_plural = _("Groupes de couches")

extra = 2 class-attribute instance-attribute

model = models.LayerGroupMp class-attribute instance-attribute

verbose_name = _('Groupe de couche') class-attribute instance-attribute

verbose_name_plural = _('Groupes de couches') class-attribute instance-attribute

OgcServerAdmin

Bases: ModelAdmin

Source code in src/georama/webgis/admin.py
121
122
class OgcServerAdmin(admin.ModelAdmin):
    list_display = ("name", "url")

list_display = ('name', 'url') class-attribute instance-attribute

ThemeAdmin

Bases: SortableAdminMixin, ModelAdmin

Source code in src/georama/webgis/admin.py
 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
class ThemeAdmin(SortableAdminMixin, admin.ModelAdmin):
    # overwrite this directly to circumnavigate problem of template which otherwise is located in different
    # path
    change_list_template = "admin/webgis/publishedastheme/change_list.html"
    list_display = ("name",)
    # inlines = [
    #     LayergroupmpInlines,
    # ]

    def get_urls(self):
        urls = super().get_urls()
        my_urls = [
            path("projects", self.admin_site.admin_view(self.projects), name="projects")
        ]
        return my_urls + urls

    def projects(self, request: HttpRequest, extra_context=None):
        publishable_projects = Project.objects.all()
        extra_context = extra_context or {}
        extra_context.update(
            dict(
                # Include common variables for rendering the admin template.
                self.admin_site.each_context(request),
                # Anything else you want in the context...
                publishable_projects=publishable_projects,
            )
        )
        return TemplateResponse(
            request, "admin/webgis/publishedastheme/projects.html", extra_context
        )

change_list_template = 'admin/webgis/publishedastheme/change_list.html' class-attribute instance-attribute

list_display = ('name') class-attribute instance-attribute

get_urls()

Source code in src/georama/webgis/admin.py
 98
 99
100
101
102
103
def get_urls(self):
    urls = super().get_urls()
    my_urls = [
        path("projects", self.admin_site.admin_view(self.projects), name="projects")
    ]
    return my_urls + urls

projects(request, extra_context=None)

Source code in src/georama/webgis/admin.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
def projects(self, request: HttpRequest, extra_context=None):
    publishable_projects = Project.objects.all()
    extra_context = extra_context or {}
    extra_context.update(
        dict(
            # Include common variables for rendering the admin template.
            self.admin_site.each_context(request),
            # Anything else you want in the context...
            publishable_projects=publishable_projects,
        )
    )
    return TemplateResponse(
        request, "admin/webgis/publishedastheme/projects.html", extra_context
    )

apps

appname = 'webgis' module-attribute

ClogsConfig

Bases: AppConfig

Source code in src/georama/webgis/apps.py
6
7
8
class ClogsConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = f"georama.{appname}"

default_auto_field = 'django.db.models.BigAutoField' class-attribute instance-attribute

name = f'georama.{appname}' class-attribute instance-attribute

forms

GEOPORTAL_URLS = {'mapnv': 'https://mapnv.ch/themes', 'cartoriviera': 'https://map.cartoriviera.ch/themes', 'sitn': 'https://sitn.ne.ch/themes', 'mapbs': 'https://map.geo.bs.ch/themes'} module-attribute

HomeForm

Bases: Form

Source code in src/georama/webgis/forms.py
17
18
19
20
21
class HomeForm(forms.Form):

    geoportal_url = forms.ChoiceField(
        label="Geoportal", required=True, choices=GEOPORTAL_URLS, widget=forms.Select
    )

geoportal_url = forms.ChoiceField(label='Geoportal', required=True, choices=GEOPORTAL_URLS, widget=forms.Select) class-attribute instance-attribute

MapWidgetFor3Dgeom

Bases: OpenLayersWidget

Source code in src/georama/webgis/forms.py
12
13
14
class MapWidgetFor3Dgeom(OpenLayersWidget):
    supports_3d = True
    template_name = "gis/openlayers.html"

supports_3d = True class-attribute instance-attribute

template_name = 'gis/openlayers.html' class-attribute instance-attribute

interfaces

geomapfish

d = {'id': 1608, 'name': 'Accidents avec la part. de piétons', 'metadata': {'legend': True, 'legendImage': 'https://api3.geo.admin.ch/static/images/legends/ch.astra.unfaelle-personenschaeden_fussgaenger_fr.png', 'metadataUrl': 'https://www.geocat.ch/geonetwork/srv/ger/md.viewer#/full_view/578457c1-debb-41b9-8f2c-18d33148cfa5', 'ogcServer': 'source for http://wms.geo.admin.ch/ image/png', 'queryLayers': 'ch.astra.unfaelle-personenschaeden_fussgaenger'}, 'dimensions': {}, 'type': 'WMTS', 'url': 'https://wmts.geo.admin.ch/EPSG/2056/1.0.0/WMTSCapabilities.xml', 'matrixSet': '2056', 'layer': 'ch.astra.unfaelle-personenschaeden_fussgaenger', 'imageType': 'image/png'} module-attribute

load_geoportal_config(themes_json_dict)

Source code in src/georama/webgis/interfaces/geomapfish/__init__.py
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
def load_geoportal_config(themes_json_dict: dict) -> ThemesJson | None:
    config = ParserConfig(fail_on_unknown_properties=False)
    decoder = CustomDictDecoder(config)

    themes_json = ThemesJson()
    for ogc_key in themes_json_dict["ogcServers"]:
        ogc_server = decoder.decode(themes_json_dict["ogcServers"][ogc_key], OgcServer)
        ogc_server.name = ogc_key
        if isinstance(themes_json_dict["ogcServers"][ogc_key]["attributes"], dict):
            for linked_layer_key in themes_json_dict["ogcServers"][ogc_key]["attributes"]:
                linked_layer = LinkedLayer(name=linked_layer_key)
                for attr_key in themes_json_dict["ogcServers"][ogc_key]["attributes"][
                    linked_layer_key
                ]:
                    attribute = decoder.decode(
                        themes_json_dict["ogcServers"][ogc_key]["attributes"][
                            linked_layer_key
                        ][attr_key],
                        Attribute,
                    )
                    attribute.name = attr_key
                    linked_layer.attributes.append(attribute)
                ogc_server.attributes.append(linked_layer)

        themes_json.ogc_servers.append(ogc_server)
    themes = decoder.decode({"themes": themes_json_dict["themes"]}, Themes)
    themes_json.themes = themes.themes
    return themes_json

load_geoportal_config_from_path(path)

Source code in src/georama/webgis/interfaces/geomapfish/__init__.py
77
78
79
def load_geoportal_config_from_path(path: str) -> ThemesJson | None:
    with open(path, mode="rb") as f:
        return load_geoportal_config(json.load(f))

load_geoportal_config_from_url(url)

Source code in src/georama/webgis/interfaces/geomapfish/__init__.py
67
68
69
70
71
72
73
74
def load_geoportal_config_from_url(url: str) -> ThemesJson | None:
    try:
        response = requests.get(url)
        response_dict = response.json()
    except Exception as e:
        logging.info(f"Could not load themes json from url. Error was {e}")
        return None
    return load_geoportal_config(response_dict)

themes_json_2_8

dataclasses
AbstractSchema dataclass
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
 9
10
11
12
13
14
15
@dataclass
class AbstractSchema:
    # field_mapping: dict
    # django_model_class: Model

    def to_django_model_instance(self):
        raise NotImplementedError
__init__()
to_django_model_instance()
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
14
15
def to_django_model_instance(self):
    raise NotImplementedError
Attribute dataclass

Bases: AbstractSchema

Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
26
27
28
29
30
31
32
@dataclass
class Attribute(AbstractSchema):
    name: str = field(default=None, metadata={"type": "Element", "required": False})
    type: str = field(default=None, metadata={"type": "Element", "required": False})
    namespace: str = field(default=None, metadata={"type": "Element", "required": False})
    minOccurs: str = field(default=None, metadata={"type": "Element", "required": False})
    maxOccurs: str = field(default=None, metadata={"type": "Element", "required": False})
maxOccurs = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
minOccurs = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
name = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
namespace = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
type = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
__init__(name=None, type=None, namespace=None, minOccurs=None, maxOccurs=None)
Dimensions dataclass
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
158
159
160
@dataclass
class Dimensions:
    Time: str = field(default=None, metadata={"type": "Element", "required": True})
Time = field(default=None, metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
__init__(Time=None)
LayerGroup dataclass
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
@dataclass
class LayerGroup:
    id: Union[int, str] = field(metadata={"type": "Element", "required": True})
    name: str = field(metadata={"type": "Element", "required": True})
    # TODO: This has to be modeled differntly because its to ambiguous
    metadata: MetaData = field(metadata={"type": "Element", "required": True})
    mixed: Optional[bool] = field(
        default=False, metadata={"type": "Element", "required": False}
    )
    children: list[Union["LayerGroup", WmsLayer, WmtsLayer]] = field(
        default_factory=list, metadata={"type": "Element", "required": False}
    )
    ogcServer: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    dimensions: Optional[Dimensions] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    path: Optional[str] = field(default=None, metadata={"type": "Element", "required": False})
children = field(default_factory=list, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
dimensions = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
id = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
metadata = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
mixed = field(default=False, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
name = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
ogcServer = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
path = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
__init__(id, name, metadata, mixed=False, children=list(), ogcServer=None, dimensions=None, path=None)
LayerSettings dataclass
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
150
151
152
153
154
155
@dataclass
class LayerSettings:
    name: str = field(metadata={"type": "Element", "required": True})
    minResolutionHint: float = field(metadata={"type": "Element", "required": True})
    maxResolutionHint: float = field(metadata={"type": "Element", "required": True})
    queryable: bool = field(metadata={"type": "Element", "required": True})
maxResolutionHint = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
minResolutionHint = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
name = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
queryable = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
__init__(name, minResolutionHint, maxResolutionHint, queryable)
LinkedLayer dataclass

Bases: AbstractSchema

Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
35
36
37
38
39
40
@dataclass
class LinkedLayer(AbstractSchema):
    name: str = field(default=None, metadata={"type": "Element", "required": False})
    attributes: list[Attribute] = field(
        default_factory=list, metadata={"type": "Element", "required": False}
    )
attributes = field(default_factory=list, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
name = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
__init__(name=None, attributes=list())
MetaData dataclass

Bases: AbstractSchema

Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
 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
@dataclass
class MetaData(AbstractSchema):
    copyable: Optional[bool] = field(
        default=False, metadata={"type": "Element", "required": False}
    )
    directedFilterAttributes: Optional[list[str]] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    disclaimer: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    enumeratedAttributes: Optional[list[str]] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    exclusiveGroup: Optional[bool] = field(
        default=False, metadata={"type": "Element", "required": False}
    )
    iconUrl: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    identifierAttributeField: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    isChecked: Optional[bool] = field(
        default=False, metadata={"type": "Element", "required": False}
    )
    isExpanded: Optional[bool] = field(
        default=False, metadata={"type": "Element", "required": False}
    )
    printNativeAngle: Optional[bool] = field(
        default=True, metadata={"type": "Element", "required": False}
    )
    isLegendExpanded: Optional[bool] = field(
        default=False, metadata={"type": "Element", "required": False}
    )
    legend: Optional[bool] = field(
        default=False, metadata={"type": "Element", "required": False}
    )
    legendImage: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    # TODO:
    # hiDPILegendImages
    legendRule: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    maxResolution: Optional[int | float] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    metadataUrl: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    minResolution: Optional[float] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    ogcServer: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    opacity: Optional[float] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    printLayers: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    queryLayers: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    thumbnail: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    timeAttribute: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    snappingConfig: Optional[SnappingConfig] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    wmsLayers: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
copyable = field(default=False, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
directedFilterAttributes = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
disclaimer = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
enumeratedAttributes = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
exclusiveGroup = field(default=False, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
iconUrl = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
identifierAttributeField = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
isChecked = field(default=False, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
isExpanded = field(default=False, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
isLegendExpanded = field(default=False, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
legend = field(default=False, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
legendImage = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
legendRule = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
maxResolution = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
metadataUrl = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
minResolution = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
ogcServer = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
opacity = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
printLayers = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
printNativeAngle = field(default=True, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
queryLayers = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
snappingConfig = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
thumbnail = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
timeAttribute = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
wmsLayers = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
__init__(copyable=False, directedFilterAttributes=None, disclaimer=None, enumeratedAttributes=None, exclusiveGroup=False, iconUrl=None, identifierAttributeField=None, isChecked=False, isExpanded=False, printNativeAngle=True, isLegendExpanded=False, legend=False, legendImage=None, legendRule=None, maxResolution=None, metadataUrl=None, minResolution=None, ogcServer=None, opacity=None, printLayers=None, queryLayers=None, thumbnail=None, timeAttribute=None, snappingConfig=None, wmsLayers=None)
OgcServer dataclass

Bases: AbstractSchema

Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@dataclass
class OgcServer(AbstractSchema):
    url: str = field(metadata={"type": "Element", "required": True})
    type: str = field(metadata={"type": "Element", "required": True})
    credential: bool = field(metadata={"type": "Element", "required": True})
    imageType: str = field(metadata={"type": "Element", "required": True})
    wfsSupport: bool = field(metadata={"type": "Element", "required": True})
    isSingleTile: bool = field(metadata={"type": "Element", "required": True})
    namespace: str = field(metadata={"type": "Element", "required": True})
    name: str = field(default=None, metadata={"type": "Element", "required": False})
    urlWfs: str = field(default=None, metadata={"type": "Element", "required": False})
    # TODO: make this correctly typed
    attributes: list[LinkedLayer] = field(
        default_factory=list, metadata={"type": "Element", "required": False}
    )
attributes = field(default_factory=list, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
credential = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
imageType = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
isSingleTile = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
name = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
namespace = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
type = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
url = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
urlWfs = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
wfsSupport = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
__init__(url, type, credential, imageType, wfsSupport, isSingleTile, namespace, name=None, urlWfs=None, attributes=list())
SnappingConfig dataclass
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
60
61
62
63
64
@dataclass
class SnappingConfig:
    edge: bool = field(default=False, metadata={"type": "Element", "required": False})
    vertex: bool = field(default=False, metadata={"type": "Element", "required": False})
    tolerance: int = field(default=0, metadata={"type": "Element", "required": False})
edge = field(default=False, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
tolerance = field(default=0, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
vertex = field(default=False, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
__init__(edge=False, vertex=False, tolerance=0)
Theme dataclass

Bases: AbstractSchema

Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
@dataclass
class Theme(AbstractSchema):
    id: Union[int, str] = field(metadata={"type": "Element", "required": True})
    name: str = field(metadata={"type": "Element", "required": True})
    icon: str = field(metadata={"type": "Element", "required": True})
    metadata: MetaData = field(metadata={"type": "Element", "required": True})
    children: list[LayerGroup] = field(
        default_factory=list, metadata={"type": "Element", "required": True}
    )

    @property
    def hash(self):
        return hashlib.md5(JsonSerializer().render(self).encode()).hexdigest()

    def separate_groups_and_layers(
        self,
        children: list[LayerGroup | WmsLayer | WmtsLayer],
        layer_list: list[WmsLayer | WmtsLayer],
        current_ogc_server: str | None = None,
        current_path: list | None = None,
    ):
        if current_path is None:
            # happens only once at initial call
            current_path = []
        for child in children:
            if isinstance(child, LayerGroup):
                current_path.append(str(child.name))
                child.path = ".".join(current_path)
                if hasattr(child, "ogcServer"):
                    if child.ogcServer is not None:
                        current_ogc_server = child.ogcServer
                        logging.debug(f"set current_ogc_server by group: {current_ogc_server}")
                    else:
                        logging.debug(
                            "New nested group but we leave ogc server because it was not redefined"
                        )
                self.separate_groups_and_layers(
                    child.children, layer_list, current_ogc_server, current_path
                )
            else:
                if child not in layer_list:
                    if isinstance(child, WmsLayer):
                        if child.ogcServer is None and current_ogc_server is not None:
                            child.ogcServer = current_ogc_server
                    child.path = ".".join(current_path + [str(child.name)])
                    layer_list.append(child)

    @property
    def unique_layers_and_groups(self) -> UniqueLayers:
        layer_list: list[WmtsLayer | WmsLayer] = []
        self.separate_groups_and_layers(self.children, layer_list)
        return UniqueLayers(elements=layer_list)
children = field(default_factory=list, metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
hash property
icon = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
id = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
metadata = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
name = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
unique_layers_and_groups property
__init__(id, name, icon, metadata, children=list())
separate_groups_and_layers(children, layer_list, current_ogc_server=None, current_path=None)
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
def separate_groups_and_layers(
    self,
    children: list[LayerGroup | WmsLayer | WmtsLayer],
    layer_list: list[WmsLayer | WmtsLayer],
    current_ogc_server: str | None = None,
    current_path: list | None = None,
):
    if current_path is None:
        # happens only once at initial call
        current_path = []
    for child in children:
        if isinstance(child, LayerGroup):
            current_path.append(str(child.name))
            child.path = ".".join(current_path)
            if hasattr(child, "ogcServer"):
                if child.ogcServer is not None:
                    current_ogc_server = child.ogcServer
                    logging.debug(f"set current_ogc_server by group: {current_ogc_server}")
                else:
                    logging.debug(
                        "New nested group but we leave ogc server because it was not redefined"
                    )
            self.separate_groups_and_layers(
                child.children, layer_list, current_ogc_server, current_path
            )
        else:
            if child not in layer_list:
                if isinstance(child, WmsLayer):
                    if child.ogcServer is None and current_ogc_server is not None:
                        child.ogcServer = current_ogc_server
                child.path = ".".join(current_path + [str(child.name)])
                layer_list.append(child)
Themes dataclass
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
313
314
315
316
317
@dataclass
class Themes:
    themes: list[Theme] = field(
        default_factory=list, metadata={"type": "Element", "required": False}
    )
themes = field(default_factory=list, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
__init__(themes=list())
ThemesJson dataclass
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
@dataclass
class ThemesJson:
    themes: list[Theme] = field(
        default_factory=list, metadata={"type": "Element", "required": False}
    )
    ogc_servers: list[OgcServer] = field(
        default_factory=list, metadata={"type": "Element", "required": False}
    )

    def get_ogc_server_by_name(self, name: str) -> OgcServer | None:
        for ogc_server in self.ogc_servers:
            if name == ogc_server.name:
                return ogc_server
        return None

    def get_theme_by_name(self, name: str) -> Theme | None:
        for theme in self.themes:
            if name == theme.name:
                return theme
        return None
ogc_servers = field(default_factory=list, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
themes = field(default_factory=list, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
__init__(themes=list(), ogc_servers=list())
get_ogc_server_by_name(name)
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
329
330
331
332
333
def get_ogc_server_by_name(self, name: str) -> OgcServer | None:
    for ogc_server in self.ogc_servers:
        if name == ogc_server.name:
            return ogc_server
    return None
get_theme_by_name(name)
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
335
336
337
338
339
def get_theme_by_name(self, name: str) -> Theme | None:
    for theme in self.themes:
        if name == theme.name:
            return theme
    return None
Time dataclass
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
@dataclass
class Time:
    minValue: str = field(default=None, metadata={"type": "Element", "required": True})
    maxValue: str = field(default=None, metadata={"type": "Element", "required": True})
    values: list[str] = field(
        default_factory=list, metadata={"type": "Element", "required": True}
    )
    # TODO: make enumeration day|month|year|second
    resolution: str = field(default=None, metadata={"type": "Element", "required": True})
    # TODO: make enumeration range|value|disabled
    mode: str = field(default=None, metadata={"type": "Element", "required": True})
    # TODO: make enumeration slider|datepicker
    widget: str = field(default=None, metadata={"type": "Element", "required": True})
    minDefValue: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": True}
    )
    maxDefValue: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": True}
    )
maxDefValue = field(default=None, metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
maxValue = field(default=None, metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
minDefValue = field(default=None, metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
minValue = field(default=None, metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
mode = field(default=None, metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
resolution = field(default=None, metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
values = field(default_factory=list, metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
widget = field(default=None, metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
__init__(minValue=None, maxValue=None, values=list(), resolution=None, mode=None, widget=None, minDefValue=None, maxDefValue=None)
UniqueLayers dataclass
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
252
253
254
255
256
@dataclass
class UniqueLayers:
    elements: list[WmsLayer | WmtsLayer] = field(
        metadata={"type": "Element", "required": True}
    )
elements = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
__init__(elements)
WmsLayer dataclass
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
@dataclass
class WmsLayer:
    id: str = field(metadata={"type": "Element", "required": True})
    name: str = field(metadata={"type": "Element", "required": True})
    # TODO: This has to be modeled differntly because its to ambiguous
    metadata: MetaData = field(metadata={"type": "Element", "required": True})
    type: str = field(metadata={"type": "Element", "required": True})
    layers: str = field(metadata={"type": "Element", "required": True})
    imageType: str = field(metadata={"type": "Element", "required": True})
    minResolutionHint: float = field(metadata={"type": "Element", "required": True})
    maxResolutionHint: float = field(metadata={"type": "Element", "required": True})
    childLayers: list[LayerSettings] = field(metadata={"type": "Element", "required": True})
    ogcServer: Optional[str] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    dimensions: Optional[Dimensions] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    editable: Optional[bool] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    style: str = field(default=None, metadata={"type": "Element", "required": False})
    time: Optional[Time] = field(default=None, metadata={"type": "Element", "required": False})
    path: Optional[str] = field(default=None, metadata={"type": "Element", "required": False})
childLayers = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
dimensions = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
editable = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
id = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
imageType = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
layers = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
maxResolutionHint = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
metadata = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
minResolutionHint = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
name = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
ogcServer = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
path = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
style = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
time = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
type = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
__init__(id, name, metadata, type, layers, imageType, minResolutionHint, maxResolutionHint, childLayers, ogcServer=None, dimensions=None, editable=None, style=None, time=None, path=None)
WmtsLayer dataclass
Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/dataclasses.py
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
@dataclass
class WmtsLayer:
    id: int = field(metadata={"type": "Element", "required": True})
    name: str = field(metadata={"type": "Element", "required": True})
    url: str = field(metadata={"type": "Element", "required": True})
    layer: str = field(metadata={"type": "Element", "required": True})
    type: str = field(metadata={"type": "Element", "required": True})
    imageType: str = field(metadata={"type": "Element", "required": True})
    # TODO: This has to be modeled differntly because its to ambiguous
    metadata: MetaData = field(metadata={"type": "Element", "required": True})
    style: str = field(default=None, metadata={"type": "Element", "required": False})
    matrix_set: str = field(default=None, metadata={"type": "Element", "required": False})
    dimensions: Optional[Dimensions] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    editable: Optional[bool] = field(
        default=None, metadata={"type": "Element", "required": False}
    )
    path: Optional[str] = field(default=None, metadata={"type": "Element", "required": False})
dimensions = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
editable = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
id = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
imageType = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
layer = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
matrix_set = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
metadata = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
name = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
path = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
style = field(default=None, metadata={'type': 'Element', 'required': False}) class-attribute instance-attribute
type = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
url = field(metadata={'type': 'Element', 'required': True}) class-attribute instance-attribute
__init__(id, name, url, layer, type, imageType, metadata, style=None, matrix_set=None, dimensions=None, editable=None, path=None)
parsers
CustomDictDecoder

Bases: DictDecoder

Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/parsers.py
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
class CustomDictDecoder(DictDecoder):
    def bind_best_dataclass(self, data: Dict, classes: Iterable[Type[T]]) -> T:
        """Bind the input data to all the given classes and return best match.

        Args:
            data: The derived element dictionary
            classes: The target class types to try

        Returns:
            An instance of one of the class types representing the parsed content.
        """
        obj = None
        keys = set(data.keys())
        max_score = -1.0
        config = replace(self.config, fail_on_converter_warnings=True)
        decoder = CustomDictDecoder(config=config, context=self.context)
        if "dimensions" in keys:
            if isinstance(data["dimensions"], dict):
                if len(data["dimensions"].keys()) == 0:
                    data["dimensions"] = None
        if "mixed" in keys and "children" in keys:
            return decoder.bind_dataclass(data, LayerGroup)
        if "type" in keys:
            if data["type"] == "WMS":
                return decoder.bind_dataclass(data, WmsLayer)
            elif data["type"] == "WMTS":
                return decoder.bind_dataclass(data, WmtsLayer)
        print(data)
        for clazz in classes:
            if not self.context.class_type.is_model(clazz):
                continue

            if self.context.local_names_match(keys, clazz):
                candidate = None
                with suppress(Exception):
                    candidate = decoder.bind_dataclass(data, clazz)

                score = self.context.class_type.score_object(candidate)
                if score > max_score:
                    max_score = score
                    obj = candidate
        if obj:
            return obj

        raise ParserError(
            f"Failed to bind object with properties({list(data.keys())}) "
            f"to any of the {[cls.__qualname__ for cls in classes]}"
        )
bind_best_dataclass(data, classes)

Bind the input data to all the given classes and return best match.

Parameters:

Name Type Description Default
data Dict

The derived element dictionary

required
classes Iterable[Type[T]]

The target class types to try

required

Returns:

Type Description
T

An instance of one of the class types representing the parsed content.

Source code in src/georama/webgis/interfaces/geomapfish/themes_json_2_8/parsers.py
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
def bind_best_dataclass(self, data: Dict, classes: Iterable[Type[T]]) -> T:
    """Bind the input data to all the given classes and return best match.

    Args:
        data: The derived element dictionary
        classes: The target class types to try

    Returns:
        An instance of one of the class types representing the parsed content.
    """
    obj = None
    keys = set(data.keys())
    max_score = -1.0
    config = replace(self.config, fail_on_converter_warnings=True)
    decoder = CustomDictDecoder(config=config, context=self.context)
    if "dimensions" in keys:
        if isinstance(data["dimensions"], dict):
            if len(data["dimensions"].keys()) == 0:
                data["dimensions"] = None
    if "mixed" in keys and "children" in keys:
        return decoder.bind_dataclass(data, LayerGroup)
    if "type" in keys:
        if data["type"] == "WMS":
            return decoder.bind_dataclass(data, WmsLayer)
        elif data["type"] == "WMTS":
            return decoder.bind_dataclass(data, WmtsLayer)
    print(data)
    for clazz in classes:
        if not self.context.class_type.is_model(clazz):
            continue

        if self.context.local_names_match(keys, clazz):
            candidate = None
            with suppress(Exception):
                candidate = decoder.bind_dataclass(data, clazz)

            score = self.context.class_type.score_object(candidate)
            if score > max_score:
                max_score = score
                obj = candidate
    if obj:
        return obj

    raise ParserError(
        f"Failed to bind object with properties({list(data.keys())}) "
        f"to any of the {[cls.__qualname__ for cls in classes]}"
    )

management

commands

clone_geoportal

Command

Bases: BaseCommand

Source code in src/georama/webgis/management/commands/clone_geoportal.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
class Command(BaseCommand):
    help = "Import configuration from themes.json data"

    def add_arguments(self, parser):
        parser.add_argument("geoportal_url", type=str)

    @transaction.atomic
    def handle(self, *args, **options):

        geoportal_url = options["geoportal_url"]

        load_geoportal(geoportal_url)

        print(f"👥 import themes from {geoportal_url}!")
help = 'Import configuration from themes.json data' class-attribute instance-attribute
add_arguments(parser)
Source code in src/georama/webgis/management/commands/clone_geoportal.py
 99
100
def add_arguments(self, parser):
    parser.add_argument("geoportal_url", type=str)
handle(*args, **options)
Source code in src/georama/webgis/management/commands/clone_geoportal.py
102
103
104
105
106
107
108
109
@transaction.atomic
def handle(self, *args, **options):

    geoportal_url = options["geoportal_url"]

    load_geoportal(geoportal_url)

    print(f"👥 import themes from {geoportal_url}!")
clone_geoportal(url)
Source code in src/georama/webgis/management/commands/clone_geoportal.py
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
def clone_geoportal(url):

    models.Theme.objects.all().delete()
    models.LayerGroupMp.objects.all().delete()
    models.Layer.objects.all().delete()
    models.LayerWms.objects.all().delete()
    r = requests.get(url)
    data = json.loads(r.content)

    import_ogc_servers(data["ogcServers"])

    for theme in data["themes"]:
        new_theme = models.Theme.objects.create(
            name=theme["name"],
            icon=theme["icon"],
            ordering=1,
            public=True,
        )
        print(f'...Importing theme: {theme["name"]}...')
        if "metadata" in theme:
            for key, value in theme["metadata"].items():
                metadata = models.Metadata.objects.create(
                    name=key,
                    value=value,
                )
                new_theme.metadata.add(metadata)

        import_layergroups(theme["children"], new_theme)
import_layergroups(children, new_theme=None, parent_node=None)
Source code in src/georama/webgis/management/commands/clone_geoportal.py
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
def import_layergroups(children, new_theme=None, parent_node=None):
    # List of theme's related layer groups, or layer groups related layer groups...
    for child in children:
        # First level
        if new_theme:
            # TODO: don't create duplicates
            group = models.LayerGroupMp.add_root(name=child["name"])
            new_theme.layergroupmp.add(group)
        # Other levels
        if parent_node:
            # TODO: don't create duplicates
            group = parent_node.add_child(name=child["name"])

            if "layers" in child:
                layer = models.Layer.objects.create(
                    name=child["name"],
                )
                layer.layergroupmp.add(group)
                if child["type"] == "WMS":
                    models.LayerWms.objects.create(
                        layer=layer,
                        ogc_server=models.OgcServer.objects.first(),
                    )

                if "metadata" in child:
                    for key, value in child["metadata"].items():
                        metadata = models.Metadata.objects.create(
                            name=key,
                            value=value,
                        )
                        layer.metadata.add(metadata)

        if len(child.keys()) > 1:
            for key, value in child.items():
                if key == "children":
                    import_layergroups(value, parent_node=group)
import_ogc_servers(data)
Source code in src/georama/webgis/management/commands/clone_geoportal.py
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
def import_ogc_servers(data):

    models.OgcServer.objects.all().delete()
    for key, value in data.items():
        models.OgcServer.objects.get_or_create(
            name=key,
            # description = data[key]["description"],
            url=data[key]["url"],
            url_wfs=data[key]["urlWfs"],
            type=data[key]["type"],
            image_type=data[key]["imageType"],
            # auth = data[key]["auth"],
            wfs_support=data[key]["wfsSupport"],
            is_single_tile=data[key]["isSingleTile"],
            attributes=data[key]["attributes"],
        )

populate_themes

Command

Bases: BaseCommand

Source code in src/georama/webgis/management/commands/populate_themes.py
164
165
166
167
168
169
170
171
172
173
174
175
176
177
class Command(BaseCommand):
    help = "Populate basic themes, layer groups and layers"

    @transaction.atomic
    def handle(self, *args, **options):
        create_functionalities()
        create_metadatas()
        create_ogc_servers()
        create_interfaces()
        create_layers()
        create_layer_groups()
        create_themes()

        print(f"👥 added demo themes, layer groups and layers for demo!")
help = 'Populate basic themes, layer groups and layers' class-attribute instance-attribute
handle(*args, **options)
Source code in src/georama/webgis/management/commands/populate_themes.py
167
168
169
170
171
172
173
174
175
176
177
@transaction.atomic
def handle(self, *args, **options):
    create_functionalities()
    create_metadatas()
    create_ogc_servers()
    create_interfaces()
    create_layers()
    create_layer_groups()
    create_themes()

    print(f"👥 added demo themes, layer groups and layers for demo!")
create_functionalities()
Source code in src/georama/webgis/management/commands/populate_themes.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def create_functionalities():
    models.Functionality.objects.all().delete()

    models.Functionality.objects.create(
        name="Functionality A",
        value="Dummy Functionality Value A",
        description="Dummy Functionality Description A",
    )

    models.Functionality.objects.create(
        name="Functionality B",
        value="Dummy Functionality Value B",
        description="Dummy Functionality Description B",
    )
create_interfaces()
Source code in src/georama/webgis/management/commands/populate_themes.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
def create_interfaces():
    models.Interface.objects.all().delete()

    models.Interface.objects.create(
        name="Desktop",
        description="Interface desktop",
    )

    models.Interface.objects.create(
        name="Mobile",
        description="Interface mobile",
    )
create_layer_groups()
Source code in src/georama/webgis/management/commands/populate_themes.py
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
def create_layer_groups():

    models.LayerGroupMp.objects.all().delete()

    wms_layer = models.Layer.objects.get(name="Layer WMS")

    root_1 = models.LayerGroupMp.add_root(name="Points d'intérêts")
    root_1.layer.set([wms_layer])
    root_1.add_child(name="Mobilité")
    child_1 = root_1.add_child(name="Transports publics")
    child_1.layer.set([wms_layer])
    child_1.add_child(name="Lignes de bus")
    child_1.add_child(name="Lignes de train")
    root_2 = models.LayerGroupMp.add_root(name="Mensuration")
    root_2.add_child(name="Limites")
    root_2.layer.set([wms_layer])
    child_2 = root_2.add_child(name="Surfaces")
    child_2.add_child(name="Couveture du sol")
    child_2.layer.set([wms_layer])
create_layers()
Source code in src/georama/webgis/management/commands/populate_themes.py
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
def create_layers():

    models.Layer.objects.all().delete()
    models.LayerWms.objects.all().delete()
    models.LayerWmts.objects.all().delete()
    interfaces = models.Interface.objects.all()
    metadatas = models.Metadata.objects.all()

    layer_wms = models.Layer.objects.create(name="Layer WMS", public=True)
    layer_wms.interface.set(interfaces)
    layer_wms.metadata.set(metadatas)

    models.LayerWms.objects.all().delete()

    models.LayerWms.objects.create(
        layer=layer_wms,
        ogc_server=models.OgcServer.objects.first(),
    )

    layer_wtms = models.Layer.objects.create(name="Layer WMTS Swisstopo", public=True)
    layer_wtms.interface.set(interfaces)
    layer_wtms.metadata.set(metadatas)

    models.LayerWmts.objects.all().delete()

    models.LayerWmts.objects.create(
        layer=layer_wtms,
    )

    layergroups = models.LayerGroupMp.objects.all()
    layer_wms.layergroupmp.set(layergroups)
create_metadatas()
Source code in src/georama/webgis/management/commands/populate_themes.py
37
38
39
40
41
42
43
44
45
46
47
def create_metadatas():

    models.Metadata.objects.all().delete()

    models.Metadata.objects.create(
        name="Test metadata A", description="Metadata fixture A", value="Dummy value A"
    )

    models.Metadata.objects.create(
        name="Test metadata B", description="Metadata fixture B", value="Dummy value B"
    )
create_ogc_servers()
Source code in src/georama/webgis/management/commands/populate_themes.py
50
51
52
53
54
55
56
57
58
59
60
61
62
def create_ogc_servers():

    models.OgcServer.objects.all().delete()

    models.OgcServer.objects.create(
        name="OGC QGIS Server",
        description="QGIS server",
        url="https://ogc.mapnv.ch/wms-mapnv",
        type="QGIS server",
        image_type="image/png",
        wfs_support=True,
        is_single_tile=True,
    )
create_themes()
Source code in src/georama/webgis/management/commands/populate_themes.py
 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
def create_themes():

    layergroups = models.LayerGroupMp.objects.all()
    metadatas = models.Metadata.objects.all()
    interfaces = models.Interface.objects.all()
    functionalities = models.Functionality.objects.all()
    models.Theme.objects.all().delete()

    theme_1 = models.Theme.objects.create(
        name="Cadastre",
        icon="cadastre.svg",
        ordering=1,
        public=True,
    )

    theme_1.layergroupmp.set(layergroups)
    theme_1.metadata.set(metadatas)
    theme_1.interface.set(interfaces)
    theme_1.functionality.set(functionalities)

    theme_2 = models.Theme.objects.create(
        name="Environnement",
        icon="environnement.svg",
        ordering=2,
        public=True,
    )

    theme_2.layergroupmp.set(layergroups)
    theme_2.metadata.set(metadatas)
    theme_2.interface.set(interfaces)
    theme_2.functionality.set(functionalities)

    theme_3 = models.Theme.objects.create(
        name="Plan de Ville",
        icon="citymap.svg",
        ordering=3,
        public=True,
    )

    theme_3.layergroupmp.set(layergroups)
    theme_3.metadata.set(metadatas)
    theme_3.interface.set(interfaces)
    theme_3.functionality.set(functionalities)

migrations

0001_initial

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0001_initial.py
 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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ("data_integration", "0020_remove_vectordataset_extent_buffer"),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name="Interface",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField()),
                ("description", models.CharField(blank=True, null=True)),
            ],
            options={
                "verbose_name": "Interface",
                "verbose_name_plural": "Interfaces",
            },
        ),
        migrations.CreateModel(
            name="LayerGroupMp",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("path", models.CharField(max_length=255, unique=True)),
                ("depth", models.PositiveIntegerField()),
                ("numchild", models.PositiveIntegerField(default=0)),
                ("themes_json_id", models.IntegerField(null=True)),
                ("name", models.CharField(max_length=128)),
                ("metadata", models.JSONField(default=None, null=True)),
                ("mixed", models.BooleanField(default=None, null=True)),
                ("ogc_server", models.CharField(default=None, max_length=2048, null=True)),
                ("dimensions", models.JSONField(default=None, null=True)),
            ],
            options={
                "verbose_name": "Groupe de de couche",
                "verbose_name_plural": "Groupes de couche",
            },
        ),
        migrations.CreateModel(
            name="HistoricalInterface",
            fields=[
                (
                    "id",
                    models.BigIntegerField(
                        auto_created=True, blank=True, db_index=True, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField()),
                ("description", models.CharField(blank=True, null=True)),
                ("history_id", models.AutoField(primary_key=True, serialize=False)),
                ("history_date", models.DateTimeField(db_index=True)),
                ("history_change_reason", models.CharField(max_length=100, null=True)),
                (
                    "history_type",
                    models.CharField(
                        choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
                        max_length=1,
                    ),
                ),
                (
                    "history_user",
                    models.ForeignKey(
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="+",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                "verbose_name": "historical Interface",
                "verbose_name_plural": "historical Interfaces",
                "ordering": ("-history_date", "-history_id"),
                "get_latest_by": ("history_date", "history_id"),
            },
            bases=(simple_history.models.HistoricalChanges, models.Model),
        ),
        migrations.CreateModel(
            name="HistoricalOgcServer",
            fields=[
                (
                    "id",
                    models.BigIntegerField(
                        auto_created=True, blank=True, db_index=True, verbose_name="ID"
                    ),
                ),
                ("url", models.URLField()),
                ("type", models.CharField()),
                ("credential", models.BooleanField(default=False)),
                ("image_type", models.CharField()),
                ("wfs_support", models.BooleanField(blank=True, null=True)),
                ("is_single_tile", models.BooleanField(blank=True, null=True)),
                ("namespace", models.CharField(null=True)),
                ("name", models.CharField(null=True)),
                ("description", models.CharField(blank=True, null=True)),
                ("url_wfs", models.URLField(blank=True, null=True)),
                ("attributes", models.JSONField(blank=True, null=True)),
                ("history_id", models.AutoField(primary_key=True, serialize=False)),
                ("history_date", models.DateTimeField(db_index=True)),
                ("history_change_reason", models.CharField(max_length=100, null=True)),
                (
                    "history_type",
                    models.CharField(
                        choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
                        max_length=1,
                    ),
                ),
                (
                    "history_user",
                    models.ForeignKey(
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="+",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "mandant",
                    models.ForeignKey(
                        blank=True,
                        db_constraint=False,
                        null=True,
                        on_delete=django.db.models.deletion.DO_NOTHING,
                        related_name="+",
                        related_query_name="ogc_server",
                        to="data_integration.mandant",
                    ),
                ),
            ],
            options={
                "verbose_name": "historical Serveur OGC",
                "verbose_name_plural": "historical Serveurs OGC",
                "ordering": ("-history_date", "-history_id"),
                "get_latest_by": ("history_date", "history_id"),
            },
            bases=(simple_history.models.HistoricalChanges, models.Model),
        ),
        migrations.CreateModel(
            name="HistoricalPublishedAsTheme",
            fields=[
                (
                    "identifier",
                    models.UUIDField(db_index=True, default=uuid.uuid4, editable=False),
                ),
                (
                    "name",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("public", models.BooleanField(default=False)),
                (
                    "title",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("description", models.TextField(blank=True, default=None, null=True)),
                (
                    "license",
                    models.TextField(
                        default="\n    This dataset is made available under the Open Database\n    License: http://opendatacommons.org/licenses/odbl/1.0/.\n    Any rights in individual contents of the database are licensed\n    under the Database Contents\n    License: http://opendatacommons.org/licenses/dbcl/1.0/\n    "
                    ),
                ),
                ("fees", models.TextField(default="No fees apply.")),
                (
                    "access_constraints",
                    models.TextField(default="No access constraints apply."),
                ),
                ("themes_json_id", models.IntegerField(null=True)),
                ("metadata", models.JSONField()),
                ("icon", models.CharField(blank=True, null=True)),
                ("ordering", models.IntegerField()),
                ("history_id", models.AutoField(primary_key=True, serialize=False)),
                ("history_date", models.DateTimeField(db_index=True)),
                ("history_change_reason", models.CharField(max_length=100, null=True)),
                (
                    "history_type",
                    models.CharField(
                        choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
                        max_length=1,
                    ),
                ),
                (
                    "history_user",
                    models.ForeignKey(
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="+",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "project",
                    models.ForeignKey(
                        blank=True,
                        db_constraint=False,
                        null=True,
                        on_delete=django.db.models.deletion.DO_NOTHING,
                        related_name="+",
                        related_query_name="published_as_geogirafe_theme",
                        to="data_integration.project",
                    ),
                ),
            ],
            options={
                "verbose_name": "historical Thème",
                "verbose_name_plural": "historical Thèmes",
                "ordering": ("-history_date", "-history_id"),
                "get_latest_by": ("history_date", "history_id"),
            },
            bases=(simple_history.models.HistoricalChanges, models.Model),
        ),
        migrations.CreateModel(
            name="HistoricalPublishedAsLayerWmts",
            fields=[
                (
                    "identifier",
                    models.UUIDField(db_index=True, default=uuid.uuid4, editable=False),
                ),
                (
                    "name",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("public", models.BooleanField(default=False)),
                (
                    "title",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("description", models.TextField(blank=True, default=None, null=True)),
                (
                    "license",
                    models.TextField(
                        default="\n    This dataset is made available under the Open Database\n    License: http://opendatacommons.org/licenses/odbl/1.0/.\n    Any rights in individual contents of the database are licensed\n    under the Database Contents\n    License: http://opendatacommons.org/licenses/dbcl/1.0/\n    "
                    ),
                ),
                ("fees", models.TextField(default="No fees apply.")),
                (
                    "access_constraints",
                    models.TextField(default="No access constraints apply."),
                ),
                ("themes_json_id", models.IntegerField(null=True)),
                ("metadata", models.JSONField(default=None, null=True)),
                ("dimensions", models.JSONField(default=None, null=True)),
                ("history_id", models.AutoField(primary_key=True, serialize=False)),
                ("history_date", models.DateTimeField(db_index=True)),
                ("history_change_reason", models.CharField(max_length=100, null=True)),
                (
                    "history_type",
                    models.CharField(
                        choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
                        max_length=1,
                    ),
                ),
                (
                    "dataset",
                    models.ForeignKey(
                        blank=True,
                        db_constraint=False,
                        null=True,
                        on_delete=django.db.models.deletion.DO_NOTHING,
                        related_name="+",
                        related_query_name="published_as_geogirafe_wmts",
                        to="data_integration.rasterdataset",
                    ),
                ),
                (
                    "history_user",
                    models.ForeignKey(
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="+",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "layer_group",
                    models.ForeignKey(
                        blank=True,
                        db_constraint=False,
                        null=True,
                        on_delete=django.db.models.deletion.DO_NOTHING,
                        related_name="+",
                        related_query_name="wmts_dataset",
                        to="webgis.layergroupmp",
                    ),
                ),
            ],
            options={
                "verbose_name": "historical WMTS Layer",
                "verbose_name_plural": "historical WMTS Layers",
                "ordering": ("-history_date", "-history_id"),
                "get_latest_by": ("history_date", "history_id"),
            },
            bases=(simple_history.models.HistoricalChanges, models.Model),
        ),
        migrations.CreateModel(
            name="HistoricalPublishedAsLayerWms",
            fields=[
                (
                    "identifier",
                    models.UUIDField(db_index=True, default=uuid.uuid4, editable=False),
                ),
                (
                    "name",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("public", models.BooleanField(default=False)),
                (
                    "title",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("description", models.TextField(blank=True, default=None, null=True)),
                (
                    "license",
                    models.TextField(
                        default="\n    This dataset is made available under the Open Database\n    License: http://opendatacommons.org/licenses/odbl/1.0/.\n    Any rights in individual contents of the database are licensed\n    under the Database Contents\n    License: http://opendatacommons.org/licenses/dbcl/1.0/\n    "
                    ),
                ),
                ("fees", models.TextField(default="No fees apply.")),
                (
                    "access_constraints",
                    models.TextField(default="No access constraints apply."),
                ),
                ("themes_json_id", models.IntegerField(null=True)),
                ("metadata", models.JSONField(default=None, null=True)),
                ("dimensions", models.JSONField(default=None, null=True)),
                ("ogc_server", models.CharField(null=True)),
                ("min_resolution_hint", models.FloatField(default=None)),
                ("max_resolution_hint", models.FloatField(default=None)),
                ("child_layers", models.JSONField(default=None)),
                ("history_id", models.AutoField(primary_key=True, serialize=False)),
                ("history_date", models.DateTimeField(db_index=True)),
                ("history_change_reason", models.CharField(max_length=100, null=True)),
                (
                    "history_type",
                    models.CharField(
                        choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
                        max_length=1,
                    ),
                ),
                (
                    "dataset",
                    models.ForeignKey(
                        blank=True,
                        db_constraint=False,
                        null=True,
                        on_delete=django.db.models.deletion.DO_NOTHING,
                        related_name="+",
                        related_query_name="published_as_geogirafe_wms",
                        to="data_integration.rasterdataset",
                    ),
                ),
                (
                    "history_user",
                    models.ForeignKey(
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="+",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "layer_group",
                    models.ForeignKey(
                        blank=True,
                        db_constraint=False,
                        null=True,
                        on_delete=django.db.models.deletion.DO_NOTHING,
                        related_name="+",
                        related_query_name="wms_dataset",
                        to="webgis.layergroupmp",
                    ),
                ),
            ],
            options={
                "verbose_name": "historical Couche WMS",
                "verbose_name_plural": "historical Couches WMS",
                "ordering": ("-history_date", "-history_id"),
                "get_latest_by": ("history_date", "history_id"),
            },
            bases=(simple_history.models.HistoricalChanges, models.Model),
        ),
        migrations.CreateModel(
            name="OgcServer",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("url", models.URLField()),
                ("type", models.CharField()),
                ("credential", models.BooleanField(default=False)),
                ("image_type", models.CharField()),
                ("wfs_support", models.BooleanField(blank=True, null=True)),
                ("is_single_tile", models.BooleanField(blank=True, null=True)),
                ("namespace", models.CharField(null=True)),
                ("name", models.CharField(null=True)),
                ("description", models.CharField(blank=True, null=True)),
                ("url_wfs", models.URLField(blank=True, null=True)),
                ("attributes", models.JSONField(blank=True, null=True)),
                (
                    "mandant",
                    models.ForeignKey(
                        null=True,
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="ogc_servers",
                        related_query_name="ogc_server",
                        to="data_integration.mandant",
                    ),
                ),
            ],
            options={
                "verbose_name": "Serveur OGC",
                "verbose_name_plural": "Serveurs OGC",
            },
        ),
        migrations.CreateModel(
            name="PublishedAsLayerWms",
            fields=[
                (
                    "identifier",
                    models.UUIDField(
                        default=uuid.uuid4, editable=False, primary_key=True, serialize=False
                    ),
                ),
                (
                    "name",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("public", models.BooleanField(default=False)),
                (
                    "title",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("description", models.TextField(blank=True, default=None, null=True)),
                (
                    "license",
                    models.TextField(
                        default="\n    This dataset is made available under the Open Database\n    License: http://opendatacommons.org/licenses/odbl/1.0/.\n    Any rights in individual contents of the database are licensed\n    under the Database Contents\n    License: http://opendatacommons.org/licenses/dbcl/1.0/\n    "
                    ),
                ),
                ("fees", models.TextField(default="No fees apply.")),
                (
                    "access_constraints",
                    models.TextField(default="No access constraints apply."),
                ),
                ("themes_json_id", models.IntegerField(null=True)),
                ("metadata", models.JSONField(default=None, null=True)),
                ("dimensions", models.JSONField(default=None, null=True)),
                ("ogc_server", models.CharField(null=True)),
                ("min_resolution_hint", models.FloatField(default=None)),
                ("max_resolution_hint", models.FloatField(default=None)),
                ("child_layers", models.JSONField(default=None)),
                (
                    "dataset",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="published_as_geogirafe_wmss",
                        related_query_name="published_as_geogirafe_wms",
                        to="data_integration.rasterdataset",
                    ),
                ),
                (
                    "layer_group",
                    models.OneToOneField(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="wms_datasets",
                        related_query_name="wms_dataset",
                        to="webgis.layergroupmp",
                    ),
                ),
            ],
            options={
                "verbose_name": "Couche WMS",
                "verbose_name_plural": "Couches WMS",
            },
        ),
        migrations.CreateModel(
            name="PublishedAsLayerWmts",
            fields=[
                (
                    "identifier",
                    models.UUIDField(
                        default=uuid.uuid4, editable=False, primary_key=True, serialize=False
                    ),
                ),
                (
                    "name",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("public", models.BooleanField(default=False)),
                (
                    "title",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("description", models.TextField(blank=True, default=None, null=True)),
                (
                    "license",
                    models.TextField(
                        default="\n    This dataset is made available under the Open Database\n    License: http://opendatacommons.org/licenses/odbl/1.0/.\n    Any rights in individual contents of the database are licensed\n    under the Database Contents\n    License: http://opendatacommons.org/licenses/dbcl/1.0/\n    "
                    ),
                ),
                ("fees", models.TextField(default="No fees apply.")),
                (
                    "access_constraints",
                    models.TextField(default="No access constraints apply."),
                ),
                ("themes_json_id", models.IntegerField(null=True)),
                ("metadata", models.JSONField(default=None, null=True)),
                ("dimensions", models.JSONField(default=None, null=True)),
                (
                    "dataset",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="published_as_geogirafe_wmtss",
                        related_query_name="published_as_geogirafe_wmts",
                        to="data_integration.rasterdataset",
                    ),
                ),
                (
                    "layer_group",
                    models.OneToOneField(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="wmts_datasets",
                        related_query_name="wmts_dataset",
                        to="webgis.layergroupmp",
                    ),
                ),
            ],
            options={
                "verbose_name": "WMTS Layer",
                "verbose_name_plural": "WMTS Layers",
            },
        ),
        migrations.CreateModel(
            name="PublishedAsTheme",
            fields=[
                (
                    "identifier",
                    models.UUIDField(
                        default=uuid.uuid4, editable=False, primary_key=True, serialize=False
                    ),
                ),
                (
                    "name",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("public", models.BooleanField(default=False)),
                (
                    "title",
                    models.CharField(blank=True, default=None, max_length=1000, null=True),
                ),
                ("description", models.TextField(blank=True, default=None, null=True)),
                (
                    "license",
                    models.TextField(
                        default="\n    This dataset is made available under the Open Database\n    License: http://opendatacommons.org/licenses/odbl/1.0/.\n    Any rights in individual contents of the database are licensed\n    under the Database Contents\n    License: http://opendatacommons.org/licenses/dbcl/1.0/\n    "
                    ),
                ),
                ("fees", models.TextField(default="No fees apply.")),
                (
                    "access_constraints",
                    models.TextField(default="No access constraints apply."),
                ),
                ("themes_json_id", models.IntegerField(null=True)),
                ("metadata", models.JSONField()),
                ("icon", models.CharField(blank=True, null=True)),
                ("ordering", models.IntegerField()),
                (
                    "project",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="published_as_geogirafe_themes",
                        related_query_name="published_as_geogirafe_theme",
                        to="data_integration.project",
                    ),
                ),
            ],
            options={
                "verbose_name": "Thème",
                "verbose_name_plural": "Thèmes",
                "ordering": ["ordering"],
            },
        ),
        migrations.AddField(
            model_name="layergroupmp",
            name="theme",
            field=models.ForeignKey(
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="tree_elements",
                related_query_name="tree_element",
                to="webgis.publishedastheme",
            ),
        ),
    ]
dependencies = [('data_integration', '0020_remove_vectordataset_extent_buffer'), migrations.swappable_dependency(settings.AUTH_USER_MODEL)] class-attribute instance-attribute
initial = True class-attribute instance-attribute
operations = [migrations.CreateModel(name='Interface', fields=[('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField()), ('description', models.CharField(blank=True, null=True))], options={'verbose_name': 'Interface', 'verbose_name_plural': 'Interfaces'}), migrations.CreateModel(name='LayerGroupMp', fields=[('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('path', models.CharField(max_length=255, unique=True)), ('depth', models.PositiveIntegerField()), ('numchild', models.PositiveIntegerField(default=0)), ('themes_json_id', models.IntegerField(null=True)), ('name', models.CharField(max_length=128)), ('metadata', models.JSONField(default=None, null=True)), ('mixed', models.BooleanField(default=None, null=True)), ('ogc_server', models.CharField(default=None, max_length=2048, null=True)), ('dimensions', models.JSONField(default=None, null=True))], options={'verbose_name': 'Groupe de de couche', 'verbose_name_plural': 'Groupes de couche'}), migrations.CreateModel(name='HistoricalInterface', fields=[('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), ('name', models.CharField()), ('description', models.CharField(blank=True, null=True)), ('history_id', models.AutoField(primary_key=True, serialize=False)), ('history_date', models.DateTimeField(db_index=True)), ('history_change_reason', models.CharField(max_length=100, null=True)), ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL))], options={'verbose_name': 'historical Interface', 'verbose_name_plural': 'historical Interfaces', 'ordering': ('-history_date', '-history_id'), 'get_latest_by': ('history_date', 'history_id')}, bases=(simple_history.models.HistoricalChanges, models.Model)), migrations.CreateModel(name='HistoricalOgcServer', fields=[('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), ('url', models.URLField()), ('type', models.CharField()), ('credential', models.BooleanField(default=False)), ('image_type', models.CharField()), ('wfs_support', models.BooleanField(blank=True, null=True)), ('is_single_tile', models.BooleanField(blank=True, null=True)), ('namespace', models.CharField(null=True)), ('name', models.CharField(null=True)), ('description', models.CharField(blank=True, null=True)), ('url_wfs', models.URLField(blank=True, null=True)), ('attributes', models.JSONField(blank=True, null=True)), ('history_id', models.AutoField(primary_key=True, serialize=False)), ('history_date', models.DateTimeField(db_index=True)), ('history_change_reason', models.CharField(max_length=100, null=True)), ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), ('mandant', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', related_query_name='ogc_server', to='data_integration.mandant'))], options={'verbose_name': 'historical Serveur OGC', 'verbose_name_plural': 'historical Serveurs OGC', 'ordering': ('-history_date', '-history_id'), 'get_latest_by': ('history_date', 'history_id')}, bases=(simple_history.models.HistoricalChanges, models.Model)), migrations.CreateModel(name='HistoricalPublishedAsTheme', fields=[('identifier', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False)), ('name', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('public', models.BooleanField(default=False)), ('title', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('description', models.TextField(blank=True, default=None, null=True)), ('license', models.TextField(default='\n This dataset is made available under the Open Database\n License: http://opendatacommons.org/licenses/odbl/1.0/.\n Any rights in individual contents of the database are licensed\n under the Database Contents\n License: http://opendatacommons.org/licenses/dbcl/1.0/\n ')), ('fees', models.TextField(default='No fees apply.')), ('access_constraints', models.TextField(default='No access constraints apply.')), ('themes_json_id', models.IntegerField(null=True)), ('metadata', models.JSONField()), ('icon', models.CharField(blank=True, null=True)), ('ordering', models.IntegerField()), ('history_id', models.AutoField(primary_key=True, serialize=False)), ('history_date', models.DateTimeField(db_index=True)), ('history_change_reason', models.CharField(max_length=100, null=True)), ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), ('project', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', related_query_name='published_as_geogirafe_theme', to='data_integration.project'))], options={'verbose_name': 'historical Thème', 'verbose_name_plural': 'historical Thèmes', 'ordering': ('-history_date', '-history_id'), 'get_latest_by': ('history_date', 'history_id')}, bases=(simple_history.models.HistoricalChanges, models.Model)), migrations.CreateModel(name='HistoricalPublishedAsLayerWmts', fields=[('identifier', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False)), ('name', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('public', models.BooleanField(default=False)), ('title', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('description', models.TextField(blank=True, default=None, null=True)), ('license', models.TextField(default='\n This dataset is made available under the Open Database\n License: http://opendatacommons.org/licenses/odbl/1.0/.\n Any rights in individual contents of the database are licensed\n under the Database Contents\n License: http://opendatacommons.org/licenses/dbcl/1.0/\n ')), ('fees', models.TextField(default='No fees apply.')), ('access_constraints', models.TextField(default='No access constraints apply.')), ('themes_json_id', models.IntegerField(null=True)), ('metadata', models.JSONField(default=None, null=True)), ('dimensions', models.JSONField(default=None, null=True)), ('history_id', models.AutoField(primary_key=True, serialize=False)), ('history_date', models.DateTimeField(db_index=True)), ('history_change_reason', models.CharField(max_length=100, null=True)), ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), ('dataset', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', related_query_name='published_as_geogirafe_wmts', to='data_integration.rasterdataset')), ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), ('layer_group', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', related_query_name='wmts_dataset', to='webgis.layergroupmp'))], options={'verbose_name': 'historical WMTS Layer', 'verbose_name_plural': 'historical WMTS Layers', 'ordering': ('-history_date', '-history_id'), 'get_latest_by': ('history_date', 'history_id')}, bases=(simple_history.models.HistoricalChanges, models.Model)), migrations.CreateModel(name='HistoricalPublishedAsLayerWms', fields=[('identifier', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False)), ('name', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('public', models.BooleanField(default=False)), ('title', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('description', models.TextField(blank=True, default=None, null=True)), ('license', models.TextField(default='\n This dataset is made available under the Open Database\n License: http://opendatacommons.org/licenses/odbl/1.0/.\n Any rights in individual contents of the database are licensed\n under the Database Contents\n License: http://opendatacommons.org/licenses/dbcl/1.0/\n ')), ('fees', models.TextField(default='No fees apply.')), ('access_constraints', models.TextField(default='No access constraints apply.')), ('themes_json_id', models.IntegerField(null=True)), ('metadata', models.JSONField(default=None, null=True)), ('dimensions', models.JSONField(default=None, null=True)), ('ogc_server', models.CharField(null=True)), ('min_resolution_hint', models.FloatField(default=None)), ('max_resolution_hint', models.FloatField(default=None)), ('child_layers', models.JSONField(default=None)), ('history_id', models.AutoField(primary_key=True, serialize=False)), ('history_date', models.DateTimeField(db_index=True)), ('history_change_reason', models.CharField(max_length=100, null=True)), ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), ('dataset', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', related_query_name='published_as_geogirafe_wms', to='data_integration.rasterdataset')), ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), ('layer_group', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', related_query_name='wms_dataset', to='webgis.layergroupmp'))], options={'verbose_name': 'historical Couche WMS', 'verbose_name_plural': 'historical Couches WMS', 'ordering': ('-history_date', '-history_id'), 'get_latest_by': ('history_date', 'history_id')}, bases=(simple_history.models.HistoricalChanges, models.Model)), migrations.CreateModel(name='OgcServer', fields=[('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('url', models.URLField()), ('type', models.CharField()), ('credential', models.BooleanField(default=False)), ('image_type', models.CharField()), ('wfs_support', models.BooleanField(blank=True, null=True)), ('is_single_tile', models.BooleanField(blank=True, null=True)), ('namespace', models.CharField(null=True)), ('name', models.CharField(null=True)), ('description', models.CharField(blank=True, null=True)), ('url_wfs', models.URLField(blank=True, null=True)), ('attributes', models.JSONField(blank=True, null=True)), ('mandant', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ogc_servers', related_query_name='ogc_server', to='data_integration.mandant'))], options={'verbose_name': 'Serveur OGC', 'verbose_name_plural': 'Serveurs OGC'}), migrations.CreateModel(name='PublishedAsLayerWms', fields=[('identifier', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('public', models.BooleanField(default=False)), ('title', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('description', models.TextField(blank=True, default=None, null=True)), ('license', models.TextField(default='\n This dataset is made available under the Open Database\n License: http://opendatacommons.org/licenses/odbl/1.0/.\n Any rights in individual contents of the database are licensed\n under the Database Contents\n License: http://opendatacommons.org/licenses/dbcl/1.0/\n ')), ('fees', models.TextField(default='No fees apply.')), ('access_constraints', models.TextField(default='No access constraints apply.')), ('themes_json_id', models.IntegerField(null=True)), ('metadata', models.JSONField(default=None, null=True)), ('dimensions', models.JSONField(default=None, null=True)), ('ogc_server', models.CharField(null=True)), ('min_resolution_hint', models.FloatField(default=None)), ('max_resolution_hint', models.FloatField(default=None)), ('child_layers', models.JSONField(default=None)), ('dataset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='published_as_geogirafe_wmss', related_query_name='published_as_geogirafe_wms', to='data_integration.rasterdataset')), ('layer_group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='wms_datasets', related_query_name='wms_dataset', to='webgis.layergroupmp'))], options={'verbose_name': 'Couche WMS', 'verbose_name_plural': 'Couches WMS'}), migrations.CreateModel(name='PublishedAsLayerWmts', fields=[('identifier', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('public', models.BooleanField(default=False)), ('title', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('description', models.TextField(blank=True, default=None, null=True)), ('license', models.TextField(default='\n This dataset is made available under the Open Database\n License: http://opendatacommons.org/licenses/odbl/1.0/.\n Any rights in individual contents of the database are licensed\n under the Database Contents\n License: http://opendatacommons.org/licenses/dbcl/1.0/\n ')), ('fees', models.TextField(default='No fees apply.')), ('access_constraints', models.TextField(default='No access constraints apply.')), ('themes_json_id', models.IntegerField(null=True)), ('metadata', models.JSONField(default=None, null=True)), ('dimensions', models.JSONField(default=None, null=True)), ('dataset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='published_as_geogirafe_wmtss', related_query_name='published_as_geogirafe_wmts', to='data_integration.rasterdataset')), ('layer_group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='wmts_datasets', related_query_name='wmts_dataset', to='webgis.layergroupmp'))], options={'verbose_name': 'WMTS Layer', 'verbose_name_plural': 'WMTS Layers'}), migrations.CreateModel(name='PublishedAsTheme', fields=[('identifier', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('public', models.BooleanField(default=False)), ('title', models.CharField(blank=True, default=None, max_length=1000, null=True)), ('description', models.TextField(blank=True, default=None, null=True)), ('license', models.TextField(default='\n This dataset is made available under the Open Database\n License: http://opendatacommons.org/licenses/odbl/1.0/.\n Any rights in individual contents of the database are licensed\n under the Database Contents\n License: http://opendatacommons.org/licenses/dbcl/1.0/\n ')), ('fees', models.TextField(default='No fees apply.')), ('access_constraints', models.TextField(default='No access constraints apply.')), ('themes_json_id', models.IntegerField(null=True)), ('metadata', models.JSONField()), ('icon', models.CharField(blank=True, null=True)), ('ordering', models.IntegerField()), ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='published_as_geogirafe_themes', related_query_name='published_as_geogirafe_theme', to='data_integration.project'))], options={'verbose_name': 'Thème', 'verbose_name_plural': 'Thèmes', 'ordering': ['ordering']}), migrations.AddField(model_name='layergroupmp', name='theme', field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tree_elements', related_query_name='tree_element', to='webgis.publishedastheme'))] class-attribute instance-attribute

0002_remove_historicalogcserver_history_user_and_more

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0002_remove_historicalogcserver_history_user_and_more.py
 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
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0001_initial"),
    ]

    operations = [
        migrations.RemoveField(
            model_name="historicalogcserver",
            name="history_user",
        ),
        migrations.RemoveField(
            model_name="historicalogcserver",
            name="mandant",
        ),
        migrations.RemoveField(
            model_name="historicalpublishedaslayerwms",
            name="dataset",
        ),
        migrations.RemoveField(
            model_name="historicalpublishedaslayerwms",
            name="history_user",
        ),
        migrations.RemoveField(
            model_name="historicalpublishedaslayerwms",
            name="layer_group",
        ),
        migrations.RemoveField(
            model_name="historicalpublishedaslayerwmts",
            name="dataset",
        ),
        migrations.RemoveField(
            model_name="historicalpublishedaslayerwmts",
            name="history_user",
        ),
        migrations.RemoveField(
            model_name="historicalpublishedaslayerwmts",
            name="layer_group",
        ),
        migrations.RemoveField(
            model_name="historicalpublishedastheme",
            name="history_user",
        ),
        migrations.RemoveField(
            model_name="historicalpublishedastheme",
            name="project",
        ),
        migrations.DeleteModel(
            name="HistoricalInterface",
        ),
        migrations.DeleteModel(
            name="HistoricalOgcServer",
        ),
        migrations.DeleteModel(
            name="HistoricalPublishedAsLayerWms",
        ),
        migrations.DeleteModel(
            name="HistoricalPublishedAsLayerWmts",
        ),
        migrations.DeleteModel(
            name="HistoricalPublishedAsTheme",
        ),
    ]
dependencies = [('webgis', '0001_initial')] class-attribute instance-attribute
operations = [migrations.RemoveField(model_name='historicalogcserver', name='history_user'), migrations.RemoveField(model_name='historicalogcserver', name='mandant'), migrations.RemoveField(model_name='historicalpublishedaslayerwms', name='dataset'), migrations.RemoveField(model_name='historicalpublishedaslayerwms', name='history_user'), migrations.RemoveField(model_name='historicalpublishedaslayerwms', name='layer_group'), migrations.RemoveField(model_name='historicalpublishedaslayerwmts', name='dataset'), migrations.RemoveField(model_name='historicalpublishedaslayerwmts', name='history_user'), migrations.RemoveField(model_name='historicalpublishedaslayerwmts', name='layer_group'), migrations.RemoveField(model_name='historicalpublishedastheme', name='history_user'), migrations.RemoveField(model_name='historicalpublishedastheme', name='project'), migrations.DeleteModel(name='HistoricalInterface'), migrations.DeleteModel(name='HistoricalOgcServer'), migrations.DeleteModel(name='HistoricalPublishedAsLayerWms'), migrations.DeleteModel(name='HistoricalPublishedAsLayerWmts'), migrations.DeleteModel(name='HistoricalPublishedAsTheme')] class-attribute instance-attribute

0003_remove_publishedaslayerwms_dataset_and_more

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0003_remove_publishedaslayerwms_dataset_and_more.py
 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
class Migration(migrations.Migration):

    dependencies = [
        ("data_integration", "0023_remove_customdataset_style_and_more"),
        ("webgis", "0002_remove_historicalogcserver_history_user_and_more"),
    ]

    operations = [
        migrations.RemoveField(
            model_name="publishedaslayerwms",
            name="dataset",
        ),
        migrations.AddField(
            model_name="publishedaslayerwms",
            name="custom_dataset",
            field=models.ForeignKey(
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="published_ogc_wms_webgis",
                related_query_name="published_ogc_wms_webgis",
                to="data_integration.customdataset",
            ),
        ),
        migrations.AddField(
            model_name="publishedaslayerwms",
            name="extent_buffer",
            field=models.FloatField(default=0.0),
        ),
        migrations.AddField(
            model_name="publishedaslayerwms",
            name="raster_dataset",
            field=models.ForeignKey(
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="published_ogc_wms_webgis",
                related_query_name="published_ogc_wms_webgis",
                to="data_integration.rasterdataset",
            ),
        ),
        migrations.AddField(
            model_name="publishedaslayerwms",
            name="vector_dataset",
            field=models.ForeignKey(
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="published_ogc_wms_webgis",
                related_query_name="published_ogc_wms_webgis",
                to="data_integration.vectordataset",
            ),
        ),
    ]
dependencies = [('data_integration', '0023_remove_customdataset_style_and_more'), ('webgis', '0002_remove_historicalogcserver_history_user_and_more')] class-attribute instance-attribute
operations = [migrations.RemoveField(model_name='publishedaslayerwms', name='dataset'), migrations.AddField(model_name='publishedaslayerwms', name='custom_dataset', field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='published_ogc_wms_webgis', related_query_name='published_ogc_wms_webgis', to='data_integration.customdataset')), migrations.AddField(model_name='publishedaslayerwms', name='extent_buffer', field=models.FloatField(default=0.0)), migrations.AddField(model_name='publishedaslayerwms', name='raster_dataset', field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='published_ogc_wms_webgis', related_query_name='published_ogc_wms_webgis', to='data_integration.rasterdataset')), migrations.AddField(model_name='publishedaslayerwms', name='vector_dataset', field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='published_ogc_wms_webgis', related_query_name='published_ogc_wms_webgis', to='data_integration.vectordataset'))] class-attribute instance-attribute

0004_remove_publishedaslayerwms_themes_json_id_and_more

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0004_remove_publishedaslayerwms_themes_json_id_and_more.py
 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
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0003_remove_publishedaslayerwms_dataset_and_more"),
    ]

    operations = [
        migrations.RemoveField(
            model_name="publishedaslayerwms",
            name="themes_json_id",
        ),
        migrations.RemoveField(
            model_name="publishedaslayerwmts",
            name="themes_json_id",
        ),
        migrations.AddField(
            model_name="publishedaslayerwms",
            name="themes_json_uuid",
            field=models.UUIDField(default=uuid.uuid4, editable=False, null=True),
        ),
        migrations.AddField(
            model_name="publishedaslayerwmts",
            name="themes_json_uuid",
            field=models.UUIDField(default=uuid.uuid4, editable=False, null=True),
        ),
    ]
dependencies = [('webgis', '0003_remove_publishedaslayerwms_dataset_and_more')] class-attribute instance-attribute
operations = [migrations.RemoveField(model_name='publishedaslayerwms', name='themes_json_id'), migrations.RemoveField(model_name='publishedaslayerwmts', name='themes_json_id'), migrations.AddField(model_name='publishedaslayerwms', name='themes_json_uuid', field=models.UUIDField(default=uuid.uuid4, editable=False, null=True)), migrations.AddField(model_name='publishedaslayerwmts', name='themes_json_uuid', field=models.UUIDField(default=uuid.uuid4, editable=False, null=True))] class-attribute instance-attribute

0005_alter_layergroupmp_options_alter_ogcserver_options_and_more

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0005_alter_layergroupmp_options_alter_ogcserver_options_and_more.py
 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
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0004_remove_publishedaslayerwms_themes_json_id_and_more"),
    ]

    operations = [
        migrations.AlterModelOptions(
            name="layergroupmp",
            options={"verbose_name": "Layer Group", "verbose_name_plural": "Layer Groups"},
        ),
        migrations.AlterModelOptions(
            name="ogcserver",
            options={"verbose_name": "OGC Server", "verbose_name_plural": "OGC Servers"},
        ),
        migrations.AlterModelOptions(
            name="publishedaslayerwms",
            options={"verbose_name": "WMS Layer", "verbose_name_plural": "WMS Layers"},
        ),
        migrations.AlterModelOptions(
            name="publishedastheme",
            options={
                "ordering": ["ordering"],
                "verbose_name": "Theme",
                "verbose_name_plural": "Themes",
            },
        ),
        migrations.AlterField(
            model_name="publishedaslayerwms",
            name="max_resolution_hint",
            field=models.FloatField(default=999999999.0),
        ),
        migrations.AlterField(
            model_name="publishedaslayerwms",
            name="min_resolution_hint",
            field=models.FloatField(default=0.0),
        ),
    ]
dependencies = [('webgis', '0004_remove_publishedaslayerwms_themes_json_id_and_more')] class-attribute instance-attribute
operations = [migrations.AlterModelOptions(name='layergroupmp', options={'verbose_name': 'Layer Group', 'verbose_name_plural': 'Layer Groups'}), migrations.AlterModelOptions(name='ogcserver', options={'verbose_name': 'OGC Server', 'verbose_name_plural': 'OGC Servers'}), migrations.AlterModelOptions(name='publishedaslayerwms', options={'verbose_name': 'WMS Layer', 'verbose_name_plural': 'WMS Layers'}), migrations.AlterModelOptions(name='publishedastheme', options={'ordering': ['ordering'], 'verbose_name': 'Theme', 'verbose_name_plural': 'Themes'}), migrations.AlterField(model_name='publishedaslayerwms', name='max_resolution_hint', field=models.FloatField(default=999999999.0)), migrations.AlterField(model_name='publishedaslayerwms', name='min_resolution_hint', field=models.FloatField(default=0.0))] class-attribute instance-attribute

0006_remove_publishedaslayerwms_child_layers

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0006_remove_publishedaslayerwms_child_layers.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0005_alter_layergroupmp_options_alter_ogcserver_options_and_more"),
    ]

    operations = [
        migrations.RemoveField(
            model_name="publishedaslayerwms",
            name="child_layers",
        ),
    ]
dependencies = [('webgis', '0005_alter_layergroupmp_options_alter_ogcserver_options_and_more')] class-attribute instance-attribute
operations = [migrations.RemoveField(model_name='publishedaslayerwms', name='child_layers')] class-attribute instance-attribute

0007_alter_publishedaslayerwms_layer_group

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0007_alter_publishedaslayerwms_layer_group.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0006_remove_publishedaslayerwms_child_layers"),
    ]

    operations = [
        migrations.AlterField(
            model_name="publishedaslayerwms",
            name="layer_group",
            field=models.OneToOneField(
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="wms_datasets",
                related_query_name="wms_dataset",
                to="webgis.layergroupmp",
            ),
        ),
    ]
dependencies = [('webgis', '0006_remove_publishedaslayerwms_child_layers')] class-attribute instance-attribute
operations = [migrations.AlterField(model_name='publishedaslayerwms', name='layer_group', field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wms_datasets', related_query_name='wms_dataset', to='webgis.layergroupmp'))] class-attribute instance-attribute

0008_remove_ogcserver_mandant

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0008_remove_ogcserver_mandant.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0007_alter_publishedaslayerwms_layer_group"),
    ]

    operations = [
        migrations.RemoveField(
            model_name="ogcserver",
            name="mandant",
        ),
    ]
dependencies = [('webgis', '0007_alter_publishedaslayerwms_layer_group')] class-attribute instance-attribute
operations = [migrations.RemoveField(model_name='ogcserver', name='mandant')] class-attribute instance-attribute

0009_alter_layergroupmp_options_and_more

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0009_alter_layergroupmp_options_and_more.py
 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
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0008_remove_ogcserver_mandant"),
    ]

    operations = [
        migrations.AlterModelOptions(
            name="layergroupmp",
            options={"verbose_name": "Group", "verbose_name_plural": "Groups"},
        ),
        migrations.RemoveField(
            model_name="publishedastheme",
            name="project",
        ),
        migrations.RemoveField(
            model_name="publishedastheme",
            name="themes_json_id",
        ),
        migrations.AddField(
            model_name="publishedastheme",
            name="themes_json_uuid",
            field=models.UUIDField(default=uuid.uuid4, editable=False),
        ),
    ]
dependencies = [('webgis', '0008_remove_ogcserver_mandant')] class-attribute instance-attribute
operations = [migrations.AlterModelOptions(name='layergroupmp', options={'verbose_name': 'Group', 'verbose_name_plural': 'Groups'}), migrations.RemoveField(model_name='publishedastheme', name='project'), migrations.RemoveField(model_name='publishedastheme', name='themes_json_id'), migrations.AddField(model_name='publishedastheme', name='themes_json_uuid', field=models.UUIDField(default=uuid.uuid4, editable=False))] class-attribute instance-attribute

0010_publishedastheme_project

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0010_publishedastheme_project.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Migration(migrations.Migration):

    dependencies = [
        ("data_integration", "0023_remove_customdataset_style_and_more"),
        ("webgis", "0009_alter_layergroupmp_options_and_more"),
    ]

    operations = [
        migrations.AddField(
            model_name="publishedastheme",
            name="project",
            field=models.ForeignKey(
                blank=True,
                default=None,
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="published_as_geogirafe_themes",
                related_query_name="published_as_geogirafe_theme",
                to="data_integration.project",
            ),
        ),
    ]
dependencies = [('data_integration', '0023_remove_customdataset_style_and_more'), ('webgis', '0009_alter_layergroupmp_options_and_more')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='publishedastheme', name='project', field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='published_as_geogirafe_themes', related_query_name='published_as_geogirafe_theme', to='data_integration.project'))] class-attribute instance-attribute

0011_remove_layergroupmp_themes_json_id_and_more

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0011_remove_layergroupmp_themes_json_id_and_more.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0010_publishedastheme_project"),
    ]

    operations = [
        migrations.RemoveField(
            model_name="layergroupmp",
            name="themes_json_id",
        ),
        migrations.AddField(
            model_name="layergroupmp",
            name="themes_json_uuid",
            field=models.UUIDField(default=uuid.uuid4, editable=False, null=True),
        ),
    ]
dependencies = [('webgis', '0010_publishedastheme_project')] class-attribute instance-attribute
operations = [migrations.RemoveField(model_name='layergroupmp', name='themes_json_id'), migrations.AddField(model_name='layergroupmp', name='themes_json_uuid', field=models.UUIDField(default=uuid.uuid4, editable=False, null=True))] class-attribute instance-attribute

0012_alter_ogcserver_name

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0012_alter_ogcserver_name.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0011_remove_layergroupmp_themes_json_id_and_more"),
    ]

    operations = [
        migrations.AlterField(
            model_name="ogcserver",
            name="name",
            field=models.CharField(null=True, unique=True),
        ),
    ]
dependencies = [('webgis', '0011_remove_layergroupmp_themes_json_id_and_more')] class-attribute instance-attribute
operations = [migrations.AlterField(model_name='ogcserver', name='name', field=models.CharField(null=True, unique=True))] class-attribute instance-attribute

0013_layergroupmp_title

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0013_layergroupmp_title.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0012_alter_ogcserver_name"),
    ]

    operations = [
        migrations.AddField(
            model_name="layergroupmp",
            name="title",
            field=models.CharField(blank=True, default=None, max_length=1000, null=True),
        ),
    ]
dependencies = [('webgis', '0012_alter_ogcserver_name')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='layergroupmp', name='title', field=models.CharField(blank=True, default=None, max_length=1000, null=True))] class-attribute instance-attribute

0014_publishedaslayerwms_queryable

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0014_publishedaslayerwms_queryable.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0013_layergroupmp_title"),
    ]

    operations = [
        migrations.AddField(
            model_name="publishedaslayerwms",
            name="queryable",
            field=models.BooleanField(blank=True, default=True, null=True),
        ),
    ]
dependencies = [('webgis', '0013_layergroupmp_title')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='publishedaslayerwms', name='queryable', field=models.BooleanField(blank=True, default=True, null=True))] class-attribute instance-attribute

0015_alter_publishedaslayerwms_custom_dataset_and_more

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0015_alter_publishedaslayerwms_custom_dataset_and_more.py
 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
class Migration(migrations.Migration):

    dependencies = [
        ("data_integration", "0023_remove_customdataset_style_and_more"),
        ("webgis", "0014_publishedaslayerwms_queryable"),
    ]

    operations = [
        migrations.AlterField(
            model_name="publishedaslayerwms",
            name="custom_dataset",
            field=models.ForeignKey(
                blank=True,
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="published_ogc_wms_webgis",
                related_query_name="published_ogc_wms_webgis",
                to="data_integration.customdataset",
            ),
        ),
        migrations.AlterField(
            model_name="publishedaslayerwms",
            name="layer_group",
            field=models.OneToOneField(
                blank=True,
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="wms_datasets",
                related_query_name="wms_dataset",
                to="webgis.layergroupmp",
            ),
        ),
        migrations.AlterField(
            model_name="publishedaslayerwms",
            name="raster_dataset",
            field=models.ForeignKey(
                blank=True,
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="published_ogc_wms_webgis",
                related_query_name="published_ogc_wms_webgis",
                to="data_integration.rasterdataset",
            ),
        ),
        migrations.AlterField(
            model_name="publishedaslayerwms",
            name="vector_dataset",
            field=models.ForeignKey(
                blank=True,
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="published_ogc_wms_webgis",
                related_query_name="published_ogc_wms_webgis",
                to="data_integration.vectordataset",
            ),
        ),
    ]
dependencies = [('data_integration', '0023_remove_customdataset_style_and_more'), ('webgis', '0014_publishedaslayerwms_queryable')] class-attribute instance-attribute
operations = [migrations.AlterField(model_name='publishedaslayerwms', name='custom_dataset', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='published_ogc_wms_webgis', related_query_name='published_ogc_wms_webgis', to='data_integration.customdataset')), migrations.AlterField(model_name='publishedaslayerwms', name='layer_group', field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wms_datasets', related_query_name='wms_dataset', to='webgis.layergroupmp')), migrations.AlterField(model_name='publishedaslayerwms', name='raster_dataset', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='published_ogc_wms_webgis', related_query_name='published_ogc_wms_webgis', to='data_integration.rasterdataset')), migrations.AlterField(model_name='publishedaslayerwms', name='vector_dataset', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='published_ogc_wms_webgis', related_query_name='published_ogc_wms_webgis', to='data_integration.vectordataset'))] class-attribute instance-attribute

0016_alter_publishedaslayerwms_dimensions_and_more

Migration

Bases: Migration

Source code in src/georama/webgis/migrations/0016_alter_publishedaslayerwms_dimensions_and_more.py
 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
class Migration(migrations.Migration):

    dependencies = [
        ("webgis", "0015_alter_publishedaslayerwms_custom_dataset_and_more"),
    ]

    operations = [
        migrations.AlterField(
            model_name="publishedaslayerwms",
            name="dimensions",
            field=models.JSONField(blank=True, default=None, null=True),
        ),
        migrations.AlterField(
            model_name="publishedaslayerwms",
            name="metadata",
            field=models.JSONField(blank=True, default=None, null=True),
        ),
        migrations.AlterField(
            model_name="publishedaslayerwms",
            name="queryable",
            field=models.BooleanField(blank=True, default=False, null=True),
        ),
        migrations.AlterField(
            model_name="publishedaslayerwmts",
            name="dimensions",
            field=models.JSONField(blank=True, default=None, null=True),
        ),
        migrations.AlterField(
            model_name="publishedaslayerwmts",
            name="metadata",
            field=models.JSONField(blank=True, default=None, null=True),
        ),
    ]
dependencies = [('webgis', '0015_alter_publishedaslayerwms_custom_dataset_and_more')] class-attribute instance-attribute
operations = [migrations.AlterField(model_name='publishedaslayerwms', name='dimensions', field=models.JSONField(blank=True, default=None, null=True)), migrations.AlterField(model_name='publishedaslayerwms', name='metadata', field=models.JSONField(blank=True, default=None, null=True)), migrations.AlterField(model_name='publishedaslayerwms', name='queryable', field=models.BooleanField(blank=True, default=False, null=True)), migrations.AlterField(model_name='publishedaslayerwmts', name='dimensions', field=models.JSONField(blank=True, default=None, null=True)), migrations.AlterField(model_name='publishedaslayerwmts', name='metadata', field=models.JSONField(blank=True, default=None, null=True))] class-attribute instance-attribute

models

themes

Interface

Bases: Model

Model that matches a configuration with a interface configuration (desktop, mobile, api, ...)

Source code in src/georama/webgis/models/themes.py
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class Interface(models.Model):

    """
    Model that matches a configuration with a interface configuration (desktop, mobile, api, ...)
    """

    name = models.CharField()
    description = models.CharField(blank=True, null=True)

    class Meta:
        verbose_name = _("Interface")
        verbose_name_plural = _("Interfaces")

    def __str__(self):
        return f"{self.name}"
description = models.CharField(blank=True, null=True) class-attribute instance-attribute
name = models.CharField() class-attribute instance-attribute
Meta
Source code in src/georama/webgis/models/themes.py
43
44
45
class Meta:
    verbose_name = _("Interface")
    verbose_name_plural = _("Interfaces")
verbose_name = _('Interface') class-attribute instance-attribute
verbose_name_plural = _('Interfaces') class-attribute instance-attribute
__str__()
Source code in src/georama/webgis/models/themes.py
47
48
def __str__(self):
    return f"{self.name}"

Layer

Bases: PublishedAs

Base model for geographic Layer

Source code in src/georama/webgis/models/themes.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
class Layer(PublishedAs):
    """
    Base model for geographic Layer
    """

    themes_json_uuid = models.UUIDField(default=uuid.uuid4, editable=False, null=True)
    metadata = models.JSONField(default=None, null=True, blank=True)
    dimensions = models.JSONField(default=None, null=True, blank=True)

    class Meta:
        abstract = True

    def __str__(self):
        return f"{self.name}"
dimensions = models.JSONField(default=None, null=True, blank=True) class-attribute instance-attribute
metadata = models.JSONField(default=None, null=True, blank=True) class-attribute instance-attribute
themes_json_uuid = models.UUIDField(default=uuid.uuid4, editable=False, null=True) class-attribute instance-attribute
Meta
Source code in src/georama/webgis/models/themes.py
172
173
class Meta:
    abstract = True
abstract = True class-attribute instance-attribute
__str__()
Source code in src/georama/webgis/models/themes.py
175
176
def __str__(self):
    return f"{self.name}"

LayerGroupMp

Bases: MP_Node

Recursive model from django-treebeard to handle children-parent relationships

Source code in src/georama/webgis/models/themes.py
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
class LayerGroupMp(MP_Node):
    """
    Recursive model from django-treebeard to handle children-parent relationships
    """

    themes_json_uuid = models.UUIDField(default=uuid.uuid4, editable=False, null=True)
    name = models.CharField(max_length=128)
    title = models.CharField(max_length=1000, null=True, default=None, blank=True)
    theme = models.ForeignKey(
        PublishedAsTheme,
        # TODO: this seems wrong => only because error:
        #  It is impossible to add a non-nullable field 'dataset' to ... without
        #  specifying a default. This is because the database needs something to populate existing rows.
        null=True,
        related_name="tree_elements",
        related_query_name="tree_element",
        on_delete=models.CASCADE,
    )
    # TODO: add metadata ManyToManyField
    metadata = models.JSONField(default=None, null=True)
    mixed = models.BooleanField(default=None, null=True)
    ogc_server = models.CharField(max_length=2048, default=None, null=True)
    dimensions = models.JSONField(default=None, null=True)
    node_order_by = ["name"]

    class Meta:
        verbose_name = _("Group")
        verbose_name_plural = _("Groups")

    def __str__(self):
        return f"{_('Group')}: {self.name}"

    def as_dataclass(self) -> LayerGroup:
        config = ParserConfig(fail_on_unknown_properties=False)
        metadata = None
        if self.metadata:
            metadata = DictDecoder(config).decode(self.metadata, MetaData)
        dimensions = None
        if self.dimensions:
            dimensions = DictDecoder(config).decode(self.dimensions, Dimensions)
        return LayerGroup(
            id=str(self.themes_json_uuid),
            name=self.name,
            metadata=metadata,
            dimensions=dimensions,
            mixed=self.mixed,
            ogcServer=self.ogc_server,
        )
dimensions = models.JSONField(default=None, null=True) class-attribute instance-attribute
metadata = models.JSONField(default=None, null=True) class-attribute instance-attribute
mixed = models.BooleanField(default=None, null=True) class-attribute instance-attribute
name = models.CharField(max_length=128) class-attribute instance-attribute
node_order_by = ['name'] class-attribute instance-attribute
ogc_server = models.CharField(max_length=2048, default=None, null=True) class-attribute instance-attribute
theme = models.ForeignKey(PublishedAsTheme, null=True, related_name='tree_elements', related_query_name='tree_element', on_delete=models.CASCADE) class-attribute instance-attribute
themes_json_uuid = models.UUIDField(default=uuid.uuid4, editable=False, null=True) class-attribute instance-attribute
title = models.CharField(max_length=1000, null=True, default=None, blank=True) class-attribute instance-attribute
Meta
Source code in src/georama/webgis/models/themes.py
138
139
140
class Meta:
    verbose_name = _("Group")
    verbose_name_plural = _("Groups")
verbose_name = _('Group') class-attribute instance-attribute
verbose_name_plural = _('Groups') class-attribute instance-attribute
__str__()
Source code in src/georama/webgis/models/themes.py
142
143
def __str__(self):
    return f"{_('Group')}: {self.name}"
as_dataclass()
Source code in src/georama/webgis/models/themes.py
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
def as_dataclass(self) -> LayerGroup:
    config = ParserConfig(fail_on_unknown_properties=False)
    metadata = None
    if self.metadata:
        metadata = DictDecoder(config).decode(self.metadata, MetaData)
    dimensions = None
    if self.dimensions:
        dimensions = DictDecoder(config).decode(self.dimensions, Dimensions)
    return LayerGroup(
        id=str(self.themes_json_uuid),
        name=self.name,
        metadata=metadata,
        dimensions=dimensions,
        mixed=self.mixed,
        ogcServer=self.ogc_server,
    )

OgcServer

Bases: Model

Definition of cartographic servers that can be selected when configurating layers

Source code in src/georama/webgis/models/themes.py
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
class OgcServer(models.Model):
    """
    Definition of cartographic servers that can be selected when configurating layers
    """

    url = models.URLField()
    type = models.CharField()
    credential = models.BooleanField(default=False)
    image_type = models.CharField()
    wfs_support = models.BooleanField(blank=True, null=True)
    is_single_tile = models.BooleanField(blank=True, null=True)
    namespace = models.CharField(null=True)
    name = models.CharField(null=True, unique=True)
    description = models.CharField(blank=True, null=True)
    url_wfs = models.URLField(blank=True, null=True)
    attributes = models.JSONField(blank=True, null=True)

    class Meta:
        verbose_name = _("OGC Server")
        verbose_name_plural = _("OGC Servers")

    def __str__(self):
        return f"{self.name}"

    def as_dataclass(self):
        attributes: list[dataclasses.LinkedLayer] = [
            DictDecoder().decode(attribute, dataclasses.LinkedLayer)
            for attribute in self.attributes
        ]
        return dataclasses.OgcServer(
            name=self.name,
            url=self.url,
            urlWfs=self.url_wfs,
            type=self.type,
            imageType=self.image_type,
            wfsSupport=self.wfs_support,
            isSingleTile=self.is_single_tile,
            attributes=attributes,
            # TODO: Find a useful way how to set this
            credential=False,
            namespace=self.namespace,
        )

    @classmethod
    def from_dataclass(cls, clazz: dataclasses.OgcServer, mandant: Mandant) -> "OgcServer":
        return cls(
            mandant=mandant,
            url=clazz.url,
            type=clazz.type,
            credential=clazz.credential,
            image_type=clazz.imageType,
            wfs_support=clazz.wfsSupport,
            is_single_tile=clazz.isSingleTile,
            namespace=clazz.namespace,
            name=clazz.name,
            url_wfs=clazz.urlWfs,
            attributes=DictEncoder().encode(clazz.attributes),
        )
attributes = models.JSONField(blank=True, null=True) class-attribute instance-attribute
credential = models.BooleanField(default=False) class-attribute instance-attribute
description = models.CharField(blank=True, null=True) class-attribute instance-attribute
image_type = models.CharField() class-attribute instance-attribute
is_single_tile = models.BooleanField(blank=True, null=True) class-attribute instance-attribute
name = models.CharField(null=True, unique=True) class-attribute instance-attribute
namespace = models.CharField(null=True) class-attribute instance-attribute
type = models.CharField() class-attribute instance-attribute
url = models.URLField() class-attribute instance-attribute
url_wfs = models.URLField(blank=True, null=True) class-attribute instance-attribute
wfs_support = models.BooleanField(blank=True, null=True) class-attribute instance-attribute
Meta
Source code in src/georama/webgis/models/themes.py
371
372
373
class Meta:
    verbose_name = _("OGC Server")
    verbose_name_plural = _("OGC Servers")
verbose_name = _('OGC Server') class-attribute instance-attribute
verbose_name_plural = _('OGC Servers') class-attribute instance-attribute
__str__()
Source code in src/georama/webgis/models/themes.py
375
376
def __str__(self):
    return f"{self.name}"
as_dataclass()
Source code in src/georama/webgis/models/themes.py
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
def as_dataclass(self):
    attributes: list[dataclasses.LinkedLayer] = [
        DictDecoder().decode(attribute, dataclasses.LinkedLayer)
        for attribute in self.attributes
    ]
    return dataclasses.OgcServer(
        name=self.name,
        url=self.url,
        urlWfs=self.url_wfs,
        type=self.type,
        imageType=self.image_type,
        wfsSupport=self.wfs_support,
        isSingleTile=self.is_single_tile,
        attributes=attributes,
        # TODO: Find a useful way how to set this
        credential=False,
        namespace=self.namespace,
    )
from_dataclass(clazz, mandant) classmethod
Source code in src/georama/webgis/models/themes.py
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
@classmethod
def from_dataclass(cls, clazz: dataclasses.OgcServer, mandant: Mandant) -> "OgcServer":
    return cls(
        mandant=mandant,
        url=clazz.url,
        type=clazz.type,
        credential=clazz.credential,
        image_type=clazz.imageType,
        wfs_support=clazz.wfsSupport,
        is_single_tile=clazz.isSingleTile,
        namespace=clazz.namespace,
        name=clazz.name,
        url_wfs=clazz.urlWfs,
        attributes=DictEncoder().encode(clazz.attributes),
    )

PublishedAsLayerWms

Bases: Layer, PublishedAsWmsAbstract

Layer extension for WMS layer

Source code in src/georama/webgis/models/themes.py
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
class PublishedAsLayerWms(Layer, PublishedAsWmsAbstract):
    """
    Layer extension for WMS layer
    """

    published_as_type = "geogirafe_wms_layer"
    # TODO: This means we currently can add a layer only once into the tree. It is not allowed
    #       in two different groups. Is that what we want?
    layer_group = models.OneToOneField(
        LayerGroupMp,
        related_name="wms_datasets",
        related_query_name="wms_dataset",
        on_delete=models.CASCADE,
        null=True,
        blank=True,
    )
    raster_dataset = models.ForeignKey(
        RasterDataSet,
        # TODO: this seems wrong => only because error:
        #  It is impossible to add a non-nullable field 'dataset' to ... without
        #  specifying a default. This is because the database needs something to populate existing rows.
        null=True,
        related_name="published_ogc_wms_webgis",
        related_query_name="published_ogc_wms_webgis",
        on_delete=models.CASCADE,
        blank=True,
    )
    vector_dataset = models.ForeignKey(
        VectorDataSet,
        # TODO: this seems wrong => only because error:
        #  It is impossible to add a non-nullable field 'dataset' to ... without
        #  specifying a default. This is because the database needs something to populate existing rows.
        null=True,
        related_name="published_ogc_wms_webgis",
        related_query_name="published_ogc_wms_webgis",
        on_delete=models.CASCADE,
        blank=True,
    )
    custom_dataset = models.ForeignKey(
        CustomDataSet,
        # TODO: this seems wrong => only because error:
        #  It is impossible to add a non-nullable field 'dataset' to ... without
        #  specifying a default. This is because the database needs something to populate existing rows.
        null=True,
        related_name="published_ogc_wms_webgis",
        related_query_name="published_ogc_wms_webgis",
        on_delete=models.CASCADE,
        blank=True,
    )
    ogc_server = models.CharField(null=True)
    min_resolution_hint = models.FloatField(default=0.0)
    max_resolution_hint = models.FloatField(default=999999999.0)

    class Meta:
        verbose_name = f'WMS {_("Layer")}'
        verbose_name_plural = f'WMS {_("Layers")}'

    def __str__(self):
        return f"{self.name}"

    @property
    def get_raster_dataset(self) -> RasterDataSet:
        return self.raster_dataset

    @property
    def get_vector_dataset(self) -> VectorDataSet:
        return self.vector_dataset

    @property
    def get_custom_dataset(self) -> CustomDataSet:
        return self.custom_dataset

    def as_dataclass(self, geogirafe_config: ThemesJson) -> WmsLayer:
        config = ParserConfig(
            fail_on_unknown_properties=False, fail_on_unknown_attributes=False
        )
        metadata = None
        if self.metadata:
            metadata = DictDecoder(config).decode(self.metadata, MetaData)
        dimensions = None
        if self.dimensions:
            dimensions = DictDecoder(config).decode(self.dimensions, Dimensions)
        return WmsLayer(
            id=str(self.themes_json_uuid),
            name=self.name,
            # TODO: Fix layers, it has to written to the datasource
            layers=self.name,
            type="WMS",
            imageType=geogirafe_config.get_ogc_server_by_name(self.ogc_server).imageType,
            metadata=metadata,
            # TODO: Fix that, its not stored correctly
            style="default",
            # TODO: fix that
            dimensions=dimensions,
            # TODO: Fix that, it does not seem correct
            editable=False,
            path="",
            minResolutionHint=self.min_resolution_hint,
            maxResolutionHint=self.max_resolution_hint,
            ogcServer=self.ogc_server,
            childLayers=[
                LayerSettings(
                    name=self.name,
                    minResolutionHint=self.min_resolution_hint,
                    maxResolutionHint=self.max_resolution_hint,
                    queryable=bool(self.queryable),
                )
            ],
        )

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        super().save(
            force_insert=force_insert,
            force_update=force_update,
            using=using,
            update_fields=update_fields,
        )
custom_dataset = models.ForeignKey(CustomDataSet, null=True, related_name='published_ogc_wms_webgis', related_query_name='published_ogc_wms_webgis', on_delete=models.CASCADE, blank=True) class-attribute instance-attribute
get_custom_dataset property
get_raster_dataset property
get_vector_dataset property
layer_group = models.OneToOneField(LayerGroupMp, related_name='wms_datasets', related_query_name='wms_dataset', on_delete=models.CASCADE, null=True, blank=True) class-attribute instance-attribute
max_resolution_hint = models.FloatField(default=999999999.0) class-attribute instance-attribute
min_resolution_hint = models.FloatField(default=0.0) class-attribute instance-attribute
ogc_server = models.CharField(null=True) class-attribute instance-attribute
published_as_type = 'geogirafe_wms_layer' class-attribute instance-attribute
raster_dataset = models.ForeignKey(RasterDataSet, null=True, related_name='published_ogc_wms_webgis', related_query_name='published_ogc_wms_webgis', on_delete=models.CASCADE, blank=True) class-attribute instance-attribute
vector_dataset = models.ForeignKey(VectorDataSet, null=True, related_name='published_ogc_wms_webgis', related_query_name='published_ogc_wms_webgis', on_delete=models.CASCADE, blank=True) class-attribute instance-attribute
Meta
Source code in src/georama/webgis/models/themes.py
232
233
234
class Meta:
    verbose_name = f'WMS {_("Layer")}'
    verbose_name_plural = f'WMS {_("Layers")}'
verbose_name = f'WMS {_('Layer')}' class-attribute instance-attribute
verbose_name_plural = f'WMS {_('Layers')}' class-attribute instance-attribute
__str__()
Source code in src/georama/webgis/models/themes.py
236
237
def __str__(self):
    return f"{self.name}"
as_dataclass(geogirafe_config)
Source code in src/georama/webgis/models/themes.py
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
def as_dataclass(self, geogirafe_config: ThemesJson) -> WmsLayer:
    config = ParserConfig(
        fail_on_unknown_properties=False, fail_on_unknown_attributes=False
    )
    metadata = None
    if self.metadata:
        metadata = DictDecoder(config).decode(self.metadata, MetaData)
    dimensions = None
    if self.dimensions:
        dimensions = DictDecoder(config).decode(self.dimensions, Dimensions)
    return WmsLayer(
        id=str(self.themes_json_uuid),
        name=self.name,
        # TODO: Fix layers, it has to written to the datasource
        layers=self.name,
        type="WMS",
        imageType=geogirafe_config.get_ogc_server_by_name(self.ogc_server).imageType,
        metadata=metadata,
        # TODO: Fix that, its not stored correctly
        style="default",
        # TODO: fix that
        dimensions=dimensions,
        # TODO: Fix that, it does not seem correct
        editable=False,
        path="",
        minResolutionHint=self.min_resolution_hint,
        maxResolutionHint=self.max_resolution_hint,
        ogcServer=self.ogc_server,
        childLayers=[
            LayerSettings(
                name=self.name,
                minResolutionHint=self.min_resolution_hint,
                maxResolutionHint=self.max_resolution_hint,
                queryable=bool(self.queryable),
            )
        ],
    )
save(force_insert=False, force_update=False, using=None, update_fields=None)
Source code in src/georama/webgis/models/themes.py
289
290
291
292
293
294
295
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
    super().save(
        force_insert=force_insert,
        force_update=force_update,
        using=using,
        update_fields=update_fields,
    )

PublishedAsLayerWmts

Bases: Layer

Layer extension for WMTS layer

Source code in src/georama/webgis/models/themes.py
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
class PublishedAsLayerWmts(Layer):
    """
    Layer extension for WMTS layer
    """

    published_as_type = "geogirafe_wmts_layer"
    layer_group = models.OneToOneField(
        LayerGroupMp,
        related_name="wmts_datasets",
        related_query_name="wmts_dataset",
        on_delete=models.CASCADE,
    )
    dataset = models.ForeignKey(
        RasterDataSet,
        related_name="published_as_geogirafe_wmtss",
        related_query_name="published_as_geogirafe_wmts",
        on_delete=models.CASCADE,
    )

    class Meta:
        verbose_name = f'WMTS {_("Layer")}'
        verbose_name_plural = f'WMTS {_("Layers")}'

    def __str__(self):
        return f"{self.name}"

    def as_dataclass(self):
        config = ParserConfig(
            fail_on_unknown_properties=False, fail_on_unknown_attributes=False
        )
        source = DictDecoder(config).decode(self.dataset.source, WmtsSource)
        metadata = None
        if self.metadata:
            metadata = DictDecoder(config).decode(self.metadata, MetaData)
        dimensions = None
        if self.dimensions:
            dimensions = DictDecoder(config).decode(self.dimensions, Dimensions)
        return WmtsLayer(
            id=self.themes_json_id,
            name=self.name,
            url=source.url,
            layer=source.layers,
            type="WMTS",
            imageType=source.format,
            metadata=metadata,
            # TODO: Fix that, its not stored correctly
            style="default",
            matrix_set=source.tile_matrix_set,
            # TODO: fix that
            dimensions=dimensions,
            # TODO: Fix that, it does not seem correct
            editable=False,
            path="",
        )
dataset = models.ForeignKey(RasterDataSet, related_name='published_as_geogirafe_wmtss', related_query_name='published_as_geogirafe_wmts', on_delete=models.CASCADE) class-attribute instance-attribute
layer_group = models.OneToOneField(LayerGroupMp, related_name='wmts_datasets', related_query_name='wmts_dataset', on_delete=models.CASCADE) class-attribute instance-attribute
published_as_type = 'geogirafe_wmts_layer' class-attribute instance-attribute
Meta
Source code in src/georama/webgis/models/themes.py
317
318
319
class Meta:
    verbose_name = f'WMTS {_("Layer")}'
    verbose_name_plural = f'WMTS {_("Layers")}'
verbose_name = f'WMTS {_('Layer')}' class-attribute instance-attribute
verbose_name_plural = f'WMTS {_('Layers')}' class-attribute instance-attribute
__str__()
Source code in src/georama/webgis/models/themes.py
321
322
def __str__(self):
    return f"{self.name}"
as_dataclass()
Source code in src/georama/webgis/models/themes.py
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
def as_dataclass(self):
    config = ParserConfig(
        fail_on_unknown_properties=False, fail_on_unknown_attributes=False
    )
    source = DictDecoder(config).decode(self.dataset.source, WmtsSource)
    metadata = None
    if self.metadata:
        metadata = DictDecoder(config).decode(self.metadata, MetaData)
    dimensions = None
    if self.dimensions:
        dimensions = DictDecoder(config).decode(self.dimensions, Dimensions)
    return WmtsLayer(
        id=self.themes_json_id,
        name=self.name,
        url=source.url,
        layer=source.layers,
        type="WMTS",
        imageType=source.format,
        metadata=metadata,
        # TODO: Fix that, its not stored correctly
        style="default",
        matrix_set=source.tile_matrix_set,
        # TODO: fix that
        dimensions=dimensions,
        # TODO: Fix that, it does not seem correct
        editable=False,
        path="",
    )

PublishedAsTheme

Bases: PublishedAs

Top item of layer tree organization

Source code in src/georama/webgis/models/themes.py
 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
class PublishedAsTheme(PublishedAs):
    """
    Top item of layer tree organization
    """

    project = models.ForeignKey(
        Project,
        related_name="published_as_geogirafe_themes",
        related_query_name="published_as_geogirafe_theme",
        on_delete=models.CASCADE,
        default=None,
        blank=True,
        null=True,
    )
    themes_json_uuid = models.UUIDField(default=uuid.uuid4, editable=False)
    published_as_type = "geogirafe_theme"
    metadata = models.JSONField()
    icon = models.CharField(blank=True, null=True)
    ordering = models.IntegerField()

    @property
    def readable_identifier(self) -> str:
        return f"{self.name}.{self.name}.{self.identifier}"

    class Meta:
        ordering = ["ordering"]
        verbose_name = _("Theme")
        verbose_name_plural = _("Themes")

    def __str__(self):
        return f"{self.name}"

    def as_dataclass(self) -> Theme:
        config = ParserConfig(fail_on_unknown_properties=False)
        return Theme(
            name=self.name,
            id=str(self.themes_json_uuid),
            icon=self.icon,
            metadata=DictDecoder(config).decode(self.metadata, MetaData),
        )

    @property
    def permissions(self) -> List[PermissionInterface]:
        if self.public:
            return []
        else:
            return self.read_permissions

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        if self.name is None:
            # TODO: maybe we want this to be configurable?
            self.name = self.project.name
        if self.title is None:
            self.title = self.project.title
        super().save(
            force_insert=force_insert,
            force_update=force_update,
            using=using,
            update_fields=update_fields,
        )
icon = models.CharField(blank=True, null=True) class-attribute instance-attribute
metadata = models.JSONField() class-attribute instance-attribute
ordering = models.IntegerField() class-attribute instance-attribute
permissions property
project = models.ForeignKey(Project, related_name='published_as_geogirafe_themes', related_query_name='published_as_geogirafe_theme', on_delete=models.CASCADE, default=None, blank=True, null=True) class-attribute instance-attribute
published_as_type = 'geogirafe_theme' class-attribute instance-attribute
readable_identifier property
themes_json_uuid = models.UUIDField(default=uuid.uuid4, editable=False) class-attribute instance-attribute
Meta
Source code in src/georama/webgis/models/themes.py
75
76
77
78
class Meta:
    ordering = ["ordering"]
    verbose_name = _("Theme")
    verbose_name_plural = _("Themes")
ordering = ['ordering'] class-attribute instance-attribute
verbose_name = _('Theme') class-attribute instance-attribute
verbose_name_plural = _('Themes') class-attribute instance-attribute
__str__()
Source code in src/georama/webgis/models/themes.py
80
81
def __str__(self):
    return f"{self.name}"
as_dataclass()
Source code in src/georama/webgis/models/themes.py
83
84
85
86
87
88
89
90
def as_dataclass(self) -> Theme:
    config = ParserConfig(fail_on_unknown_properties=False)
    return Theme(
        name=self.name,
        id=str(self.themes_json_uuid),
        icon=self.icon,
        metadata=DictDecoder(config).decode(self.metadata, MetaData),
    )
save(force_insert=False, force_update=False, using=None, update_fields=None)
Source code in src/georama/webgis/models/themes.py
 99
100
101
102
103
104
105
106
107
108
109
110
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
    if self.name is None:
        # TODO: maybe we want this to be configurable?
        self.name = self.project.name
    if self.title is None:
        self.title = self.project.title
    super().save(
        force_insert=force_insert,
        force_update=force_update,
        using=using,
        update_fields=update_fields,
    )

tests

urls

URL configuration for core project.

The urlpatterns list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/5.0/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))

urlpatterns = [path('', views.home, name='home'), path('/themes.<str:format>', views.Themes.as_view(), name='themes'), path('/<str:mandant_name>/', views.GeoGirafe.as_view(), name='geogirafe'), path('/<str:mandant_name>/config.json', views.Config.as_view(), name='config'), path('/publish_project/<int:project_id>', views.PublishProject.as_view(), name='publish_project'), path('/maps', views.OgcServerWebgis.as_view(), name='webgis_ogc_entry'), path('/publish_dataset_as/wms/<str:dataset_type>/<str:dataset_id>', views.admin_publish_dataset_as_wms, name='webgis_publish_dataset_as_wms'), path('/translations/de.json', views.translation_json, name='webis_translation_json')] module-attribute

views

Config

Bases: View

Source code in src/georama/webgis/views.py
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
class Config(View):
    # TODO: This is prepared for later approach where we serve GeoGirafe directly through Django

    def get(self, request: HttpRequest, mandant_name: str):
        config_dict = {
            "general": {"locale": "en"},
            "languages": {
                "translations": {
                    "de": ["Mock/de.json"],
                    "en": ["Mock/en.json"],
                    "fr": ["Mock/fr.json"],
                },
                "defaultLanguage": "en",
            },
            "themes": {"url": "themes.json", "defaultTheme": "cadastre"},
            "basemaps": {
                "show": True,
                "defaultBasemap": "orthophoto",
                "OSM": False,
                "SwissTopoVectorTiles": True,
            },
            "treeview": {"useLegendIcons": False},
            "search": {
                "url": "https://geomapfish-demo-2-8.camptocamp.com/search?limit=30&partitionlimit=5&interface=desktop&query=###SEARCHTERM###&lang=###SEARCHLANG###"
            },
            "print": {
                "url": "https://geomapfish-demo-2-8.camptocamp.com/printproxy/",
                "formats": ["png", "pdf", "jpg", "jpeg", "notvalid"],
                "defaultFormat": "pdf",
                "layouts": ["1 A4 portrait", "4 A3 landscape"],
                "defaultLayout": "1 A4 portrait",
                "scales": [500000, 25000, 10000, 99999, 5000, 2500],
                "attributeNames": ["legend", "title", "comments"],
                "printLegend": {"showGroupsTitle": True},
            },
            "share": {  # TODO: This is prepared for later approach where we serve GeoGirafe directly through Django
                "service": "lstu",
                "createUrl": "https://lstu.fr/a",
            },
            "projections": {"EPSG:3857": "W-M", "EPSG:4326": "WGS84", "EPSG:2056": "LV95"},
            "map": {
                "srid": "EPSG:2056",
                "scales": [
                    1000000,
                    500000,
                    200000,
                    100000,
                    50000,
                    20000,
                    10000,
                    5000,
                    2000,
                    1000,
                    500,
                    200,
                ],
                "startPosition": "2612500,1268050",
                "startZoom": 8,
                "maxExtent": "2200000,1040000,3000000,1310000",
            },
            "map3d": {
                "terrainUrl": "https://terrain100.geo.admin.ch/1.0.0/ch.swisstopo.terrain.3d/",
                "tilesetsUrls": [
                    "https://vectortiles100.geo.admin.ch/3d-tiles/ch.swisstopo.swisstlm3d.3d/20201020/tileset.json"
                ],
            },
            "bookmarks": {"service": "localStorage", "get": "", "post": ""},
        }
        return HttpResponse(
            json.dumps(config_dict, indent=2), status=200, content_type="application/json"
        )

get(request, mandant_name)

Source code in src/georama/webgis/views.py
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
def get(self, request: HttpRequest, mandant_name: str):
    config_dict = {
        "general": {"locale": "en"},
        "languages": {
            "translations": {
                "de": ["Mock/de.json"],
                "en": ["Mock/en.json"],
                "fr": ["Mock/fr.json"],
            },
            "defaultLanguage": "en",
        },
        "themes": {"url": "themes.json", "defaultTheme": "cadastre"},
        "basemaps": {
            "show": True,
            "defaultBasemap": "orthophoto",
            "OSM": False,
            "SwissTopoVectorTiles": True,
        },
        "treeview": {"useLegendIcons": False},
        "search": {
            "url": "https://geomapfish-demo-2-8.camptocamp.com/search?limit=30&partitionlimit=5&interface=desktop&query=###SEARCHTERM###&lang=###SEARCHLANG###"
        },
        "print": {
            "url": "https://geomapfish-demo-2-8.camptocamp.com/printproxy/",
            "formats": ["png", "pdf", "jpg", "jpeg", "notvalid"],
            "defaultFormat": "pdf",
            "layouts": ["1 A4 portrait", "4 A3 landscape"],
            "defaultLayout": "1 A4 portrait",
            "scales": [500000, 25000, 10000, 99999, 5000, 2500],
            "attributeNames": ["legend", "title", "comments"],
            "printLegend": {"showGroupsTitle": True},
        },
        "share": {  # TODO: This is prepared for later approach where we serve GeoGirafe directly through Django
            "service": "lstu",
            "createUrl": "https://lstu.fr/a",
        },
        "projections": {"EPSG:3857": "W-M", "EPSG:4326": "WGS84", "EPSG:2056": "LV95"},
        "map": {
            "srid": "EPSG:2056",
            "scales": [
                1000000,
                500000,
                200000,
                100000,
                50000,
                20000,
                10000,
                5000,
                2000,
                1000,
                500,
                200,
            ],
            "startPosition": "2612500,1268050",
            "startZoom": 8,
            "maxExtent": "2200000,1040000,3000000,1310000",
        },
        "map3d": {
            "terrainUrl": "https://terrain100.geo.admin.ch/1.0.0/ch.swisstopo.terrain.3d/",
            "tilesetsUrls": [
                "https://vectortiles100.geo.admin.ch/3d-tiles/ch.swisstopo.swisstlm3d.3d/20201020/tileset.json"
            ],
        },
        "bookmarks": {"service": "localStorage", "get": "", "post": ""},
    }
    return HttpResponse(
        json.dumps(config_dict, indent=2), status=200, content_type="application/json"
    )

GeoGirafe

Bases: View

Source code in src/georama/webgis/views.py
313
314
315
316
317
class GeoGirafe(View):
    # TODO: This is prepared for later approach where we serve GeoGirafe directly through Django

    def get(self, request: HttpRequest, mandant_name: str):
        return render(request, "geogirafe/index.html")

get(request, mandant_name)

Source code in src/georama/webgis/views.py
316
317
def get(self, request: HttpRequest, mandant_name: str):
    return render(request, "geogirafe/index.html")

OgcServerWebgis

Bases: OgcServer

Source code in src/georama/webgis/views.py
525
526
class OgcServerWebgis(OgcServer):
    model = PublishedAsLayerWms

model = PublishedAsLayerWms class-attribute instance-attribute

PublishProject

Bases: View

Source code in src/georama/webgis/views.py
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
class PublishProject(View):
    @staticmethod
    def find_dataset_by_name(
        dataset_name: str,
        datasets: List[QslGroup] | List[QslRaster] | List[QslVector] | List[QslCustom],
    ) -> QslGroup | QslVector | QslRaster | QslCustom | None:
        # TODO: This should be move directly to the QSL interface!
        for element in datasets:
            if element.name == dataset_name:
                return element
        return None

    def assemble_tree_to_treebeard(
        self,
        children: List[str],
        current_parent: LayerGroupMp,
        theme: PublishedAsTheme,
        project: Project,
        project_config: QslConfig,
        current_ogc_server: str | None = None,
    ):
        for child in children:
            node = current_parent.add_child(name=child)
            db_node = LayerGroupMp.objects.get(pk=node.pk)
            db_node.theme = theme
            db_node.save()
            group_match = self.find_dataset_by_name(child, project_config.datasets.group)
            if group_match:
                # TODO: Improve regarding GMF possibilities!
                db_node.title = group_match.title
                db_node.metadata = {}
                db_node.mixed = False
                db_node.ogc_server = current_ogc_server
                db_node.dimensions = {}
                db_node.save()
                self.assemble_tree_to_treebeard(
                    project_config.tree.find_by_name(child).children,
                    db_node,
                    theme,
                    project,
                    project_config,
                    current_ogc_server,
                )
            else:
                raster_match = self.find_dataset_by_name(child, project_config.datasets.raster)
                vector_match = self.find_dataset_by_name(child, project_config.datasets.vector)
                custom_match = self.find_dataset_by_name(child, project_config.datasets.custom)
                if raster_match:
                    query = RasterDataSet.objects.filter(project=project, name=child)
                    if query.exists():
                        dataset = query.get()
                    else:
                        logging.error(f"Could not find raster dataset with name '{child}'")
                        raise AttributeError()
                    PublishedAsLayerWms(
                        ogc_server=current_ogc_server,
                        name=dataset.name,
                        title=dataset.title,
                        raster_dataset=dataset,
                        layer_group=db_node,
                        dimensions={},
                        public=True,
                    ).save()
                elif vector_match:
                    query = VectorDataSet.objects.filter(project=project, name=child)
                    if query.exists():
                        dataset = query.get()
                    else:
                        logging.error(f"Could not find vector dataset with name '{child}'")
                        raise AttributeError()
                    PublishedAsLayerWms(
                        ogc_server=current_ogc_server,
                        name=dataset.name,
                        title=dataset.title,
                        vector_dataset=dataset,
                        layer_group=db_node,
                        dimensions={},
                        public=True,
                    ).save()
                elif custom_match:
                    query = CustomDataSet.objects.filter(project=project, name=child)
                    if query.exists():
                        dataset = query.get()
                    else:
                        logging.error(f"Could not find custom dataset with name '{child}'")
                        raise AttributeError()
                    PublishedAsLayerWms(
                        ogc_server=current_ogc_server,
                        name=dataset.name,
                        title=dataset.title,
                        custom_dataset=dataset,
                        layer_group=db_node,
                        dimensions={},
                        public=True,
                    ).save()
                else:
                    raise NotImplementedError(
                        f"Layer type is not implemented: {child.__class__.__name__}"
                    )

    def get(self, request: HttpRequest, project_id: int, **kwargs):
        project_db = Project.objects.get(id=project_id)
        highest_theme = PublishedAsTheme.objects.order_by("ordering").last()
        theme = PublishedAsTheme(
            name=project_db.name,
            title=project_db.title,
            project=project_db,
            metadata={"isLegendExpanded": True, "legend": False},
            ordering=highest_theme.ordering + 1 if highest_theme else 1,
        )
        theme.save()
        ogc_server = insert_internal_ogc_server(request)
        project_from_config, project_config = RegisterQgisProject.load_project_config(
            project_db.mandant.name, project_db.name
        )
        root_group = LayerGroupMp.add_root(name=theme.name)
        db_root_node = LayerGroupMp.objects.get(pk=root_group.pk)
        db_root_node.theme = theme
        db_root_node.save()
        # Highly recursive task, we flatten the tree into treebeard structure
        self.assemble_tree_to_treebeard(
            # the element with empty string as name is always the root of the tree
            project_config.tree.find_by_name("").children,
            db_root_node,
            theme,
            project_db,
            project_config,
            ogc_server.name,
        )
        return redirect("admin:webgis_publishedastheme_changelist")

assemble_tree_to_treebeard(children, current_parent, theme, project, project_config, current_ogc_server=None)

Source code in src/georama/webgis/views.py
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
def assemble_tree_to_treebeard(
    self,
    children: List[str],
    current_parent: LayerGroupMp,
    theme: PublishedAsTheme,
    project: Project,
    project_config: QslConfig,
    current_ogc_server: str | None = None,
):
    for child in children:
        node = current_parent.add_child(name=child)
        db_node = LayerGroupMp.objects.get(pk=node.pk)
        db_node.theme = theme
        db_node.save()
        group_match = self.find_dataset_by_name(child, project_config.datasets.group)
        if group_match:
            # TODO: Improve regarding GMF possibilities!
            db_node.title = group_match.title
            db_node.metadata = {}
            db_node.mixed = False
            db_node.ogc_server = current_ogc_server
            db_node.dimensions = {}
            db_node.save()
            self.assemble_tree_to_treebeard(
                project_config.tree.find_by_name(child).children,
                db_node,
                theme,
                project,
                project_config,
                current_ogc_server,
            )
        else:
            raster_match = self.find_dataset_by_name(child, project_config.datasets.raster)
            vector_match = self.find_dataset_by_name(child, project_config.datasets.vector)
            custom_match = self.find_dataset_by_name(child, project_config.datasets.custom)
            if raster_match:
                query = RasterDataSet.objects.filter(project=project, name=child)
                if query.exists():
                    dataset = query.get()
                else:
                    logging.error(f"Could not find raster dataset with name '{child}'")
                    raise AttributeError()
                PublishedAsLayerWms(
                    ogc_server=current_ogc_server,
                    name=dataset.name,
                    title=dataset.title,
                    raster_dataset=dataset,
                    layer_group=db_node,
                    dimensions={},
                    public=True,
                ).save()
            elif vector_match:
                query = VectorDataSet.objects.filter(project=project, name=child)
                if query.exists():
                    dataset = query.get()
                else:
                    logging.error(f"Could not find vector dataset with name '{child}'")
                    raise AttributeError()
                PublishedAsLayerWms(
                    ogc_server=current_ogc_server,
                    name=dataset.name,
                    title=dataset.title,
                    vector_dataset=dataset,
                    layer_group=db_node,
                    dimensions={},
                    public=True,
                ).save()
            elif custom_match:
                query = CustomDataSet.objects.filter(project=project, name=child)
                if query.exists():
                    dataset = query.get()
                else:
                    logging.error(f"Could not find custom dataset with name '{child}'")
                    raise AttributeError()
                PublishedAsLayerWms(
                    ogc_server=current_ogc_server,
                    name=dataset.name,
                    title=dataset.title,
                    custom_dataset=dataset,
                    layer_group=db_node,
                    dimensions={},
                    public=True,
                ).save()
            else:
                raise NotImplementedError(
                    f"Layer type is not implemented: {child.__class__.__name__}"
                )

find_dataset_by_name(dataset_name, datasets) staticmethod

Source code in src/georama/webgis/views.py
394
395
396
397
398
399
400
401
402
403
@staticmethod
def find_dataset_by_name(
    dataset_name: str,
    datasets: List[QslGroup] | List[QslRaster] | List[QslVector] | List[QslCustom],
) -> QslGroup | QslVector | QslRaster | QslCustom | None:
    # TODO: This should be move directly to the QSL interface!
    for element in datasets:
        if element.name == dataset_name:
            return element
    return None

get(request, project_id, **kwargs)

Source code in src/georama/webgis/views.py
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
def get(self, request: HttpRequest, project_id: int, **kwargs):
    project_db = Project.objects.get(id=project_id)
    highest_theme = PublishedAsTheme.objects.order_by("ordering").last()
    theme = PublishedAsTheme(
        name=project_db.name,
        title=project_db.title,
        project=project_db,
        metadata={"isLegendExpanded": True, "legend": False},
        ordering=highest_theme.ordering + 1 if highest_theme else 1,
    )
    theme.save()
    ogc_server = insert_internal_ogc_server(request)
    project_from_config, project_config = RegisterQgisProject.load_project_config(
        project_db.mandant.name, project_db.name
    )
    root_group = LayerGroupMp.add_root(name=theme.name)
    db_root_node = LayerGroupMp.objects.get(pk=root_group.pk)
    db_root_node.theme = theme
    db_root_node.save()
    # Highly recursive task, we flatten the tree into treebeard structure
    self.assemble_tree_to_treebeard(
        # the element with empty string as name is always the root of the tree
        project_config.tree.find_by_name("").children,
        db_root_node,
        theme,
        project_db,
        project_config,
        ogc_server.name,
    )
    return redirect("admin:webgis_publishedastheme_changelist")

RegisterThemesJson

Bases: View

Source code in src/georama/webgis/views.py
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
class RegisterThemesJson(View):
    def post(self, request: HttpRequest):
        form = HomeForm(request.POST)
        if form.is_valid():
            url = GEOPORTAL_URLS[form.cleaned_data["geoportal_url"]]
            geoportal_config = load_geoportal_config_from_url(url)
            if geoportal_config is None:
                return redirect("admin:clogs_publishedastheme_changelist")
            mandant_qs = Mandant.objects.filter(name=form.cleaned_data["geoportal_url"])
            if not mandant_qs.exists():
                mandant_db = Mandant(name=form.cleaned_data["geoportal_url"], description=url)
                mandant_db.save()
            else:
                # we can do so, because name is unique in DB
                mandant_db = mandant_qs.get()
            for ogc_server in geoportal_config.ogc_servers:
                OgcServer.from_dataclass(ogc_server, mandant_db).save()
            for order, theme in enumerate(geoportal_config.themes):
                project_qs = Project.objects.filter(name=theme.name, mandant=mandant_db)
                if not project_qs.exists():
                    project_db = Project(
                        mandant=mandant_db,
                        name=theme.name,
                        hash=theme.hash,
                        # TODO: Fix this to correct title (via translation?)
                        title=theme.name.title(),
                    )
                    project_db.save()

                    published_theme = PublishedAsTheme(
                        themes_json_id=theme.id,
                        project=project_db,
                        name=theme.name,
                        public=True,
                        ordering=order,
                        icon=theme.icon,
                        # TODO: we go the cheap way here, lets investigate later....
                        metadata=DictEncoder().encode(theme.metadata),
                    )
                    published_theme.save()
                    root_group = LayerGroupMp.add_root(name=theme.name)
                    db_root_node = LayerGroupMp.objects.get(pk=root_group.pk)
                    db_root_node.theme = published_theme
                    db_root_node.save()
                    # Highly recursive task, we flatten the tree into treebeard structure
                    assemble_tree_to_treebeard(
                        theme.children,
                        db_root_node,
                        published_theme,
                        project_db,
                        geoportal_config,
                    )
                else:
                    # TODO: Handle update etc. of projects
                    logging.debug(
                        "Theme existed. Updating process not implemented "
                        "yet => delete the project and integrate it again!"
                    )
        else:
            # TODO: Add appropriate handling
            logging.debug("Form was not valid!")
        return redirect("admin:clogs_publishedastheme_changelist")

post(request)

Source code in src/georama/webgis/views.py
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
def post(self, request: HttpRequest):
    form = HomeForm(request.POST)
    if form.is_valid():
        url = GEOPORTAL_URLS[form.cleaned_data["geoportal_url"]]
        geoportal_config = load_geoportal_config_from_url(url)
        if geoportal_config is None:
            return redirect("admin:clogs_publishedastheme_changelist")
        mandant_qs = Mandant.objects.filter(name=form.cleaned_data["geoportal_url"])
        if not mandant_qs.exists():
            mandant_db = Mandant(name=form.cleaned_data["geoportal_url"], description=url)
            mandant_db.save()
        else:
            # we can do so, because name is unique in DB
            mandant_db = mandant_qs.get()
        for ogc_server in geoportal_config.ogc_servers:
            OgcServer.from_dataclass(ogc_server, mandant_db).save()
        for order, theme in enumerate(geoportal_config.themes):
            project_qs = Project.objects.filter(name=theme.name, mandant=mandant_db)
            if not project_qs.exists():
                project_db = Project(
                    mandant=mandant_db,
                    name=theme.name,
                    hash=theme.hash,
                    # TODO: Fix this to correct title (via translation?)
                    title=theme.name.title(),
                )
                project_db.save()

                published_theme = PublishedAsTheme(
                    themes_json_id=theme.id,
                    project=project_db,
                    name=theme.name,
                    public=True,
                    ordering=order,
                    icon=theme.icon,
                    # TODO: we go the cheap way here, lets investigate later....
                    metadata=DictEncoder().encode(theme.metadata),
                )
                published_theme.save()
                root_group = LayerGroupMp.add_root(name=theme.name)
                db_root_node = LayerGroupMp.objects.get(pk=root_group.pk)
                db_root_node.theme = published_theme
                db_root_node.save()
                # Highly recursive task, we flatten the tree into treebeard structure
                assemble_tree_to_treebeard(
                    theme.children,
                    db_root_node,
                    published_theme,
                    project_db,
                    geoportal_config,
                )
            else:
                # TODO: Handle update etc. of projects
                logging.debug(
                    "Theme existed. Updating process not implemented "
                    "yet => delete the project and integrate it again!"
                )
    else:
        # TODO: Add appropriate handling
        logging.debug("Form was not valid!")
    return redirect("admin:clogs_publishedastheme_changelist")

Themes

Bases: View

Source code in src/georama/webgis/views.py
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
class Themes(View):
    def assemble_themes_tree_from_treebeard(
        self,
        node: LayerGroupMp,
        layer_group: LayerGroup | Theme,
        config: ThemesJson,
        user: User,
    ):
        for child in node.get_children():
            if child.get_children():
                # this is a group to unpack
                group = child.as_dataclass()
                layer_group.children.append(group)
                self.assemble_themes_tree_from_treebeard(child, group, config, user)
            else:
                if hasattr(child, "wms_datasets"):
                    # we filter for permission on the onetoone field connected published_as element
                    if child.wms_datasets.has_read_permission(user, appname):
                        layer_group.children.append(child.wms_datasets.as_dataclass(config))
                elif hasattr(child, "wmts_datasets"):
                    layer_group.children.append(child.wmts_datasets.as_dataclass())
                else:
                    raise NotImplementedError(f"We are not aware of the passed type {node}")

    def get(self, request: HttpRequest, format: str):
        geogirafe_config = ThemesJson()

        for ogc_server in WebGisOgcServer.objects.all():
            geogirafe_config.ogc_servers.append(ogc_server.as_dataclass())
        for theme in PublishedAsTheme.objects.all():
            theme_object = theme.as_dataclass()
            if theme_object.icon is None:
                theme_object.icon = request.build_absolute_uri(
                    static("/webgis/assets/images/georama.coming_soon.png")
                )
            geogirafe_config.themes.append(theme_object)
            root_node = theme.tree_elements.first().get_root()
            self.assemble_themes_tree_from_treebeard(
                root_node, theme_object, geogirafe_config, request.user
            )
        result_dict = {
            "themes": DictEncoder().encode(geogirafe_config.themes),
            "ogcServers": {},
            "errors": [],
            "background_layers": [],
        }
        for ogc_server in geogirafe_config.ogc_servers:
            result_dict["ogcServers"][ogc_server.name] = DictEncoder().encode(ogc_server)
        return HttpResponse(
            json.dumps(result_dict, indent=2), status=200, content_type="application/json"
        )

assemble_themes_tree_from_treebeard(node, layer_group, config, user)

Source code in src/georama/webgis/views.py
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
def assemble_themes_tree_from_treebeard(
    self,
    node: LayerGroupMp,
    layer_group: LayerGroup | Theme,
    config: ThemesJson,
    user: User,
):
    for child in node.get_children():
        if child.get_children():
            # this is a group to unpack
            group = child.as_dataclass()
            layer_group.children.append(group)
            self.assemble_themes_tree_from_treebeard(child, group, config, user)
        else:
            if hasattr(child, "wms_datasets"):
                # we filter for permission on the onetoone field connected published_as element
                if child.wms_datasets.has_read_permission(user, appname):
                    layer_group.children.append(child.wms_datasets.as_dataclass(config))
            elif hasattr(child, "wmts_datasets"):
                layer_group.children.append(child.wmts_datasets.as_dataclass())
            else:
                raise NotImplementedError(f"We are not aware of the passed type {node}")

get(request, format)

Source code in src/georama/webgis/views.py
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
def get(self, request: HttpRequest, format: str):
    geogirafe_config = ThemesJson()

    for ogc_server in WebGisOgcServer.objects.all():
        geogirafe_config.ogc_servers.append(ogc_server.as_dataclass())
    for theme in PublishedAsTheme.objects.all():
        theme_object = theme.as_dataclass()
        if theme_object.icon is None:
            theme_object.icon = request.build_absolute_uri(
                static("/webgis/assets/images/georama.coming_soon.png")
            )
        geogirafe_config.themes.append(theme_object)
        root_node = theme.tree_elements.first().get_root()
        self.assemble_themes_tree_from_treebeard(
            root_node, theme_object, geogirafe_config, request.user
        )
    result_dict = {
        "themes": DictEncoder().encode(geogirafe_config.themes),
        "ogcServers": {},
        "errors": [],
        "background_layers": [],
    }
    for ogc_server in geogirafe_config.ogc_servers:
        result_dict["ogcServers"][ogc_server.name] = DictEncoder().encode(ogc_server)
    return HttpResponse(
        json.dumps(result_dict, indent=2), status=200, content_type="application/json"
    )

admin_publish_dataset_as_wms(request, dataset_type, dataset_id)

helper function to hide actual connection in the database but make publishing straight forward.

Source code in src/georama/webgis/views.py
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
def admin_publish_dataset_as_wms(request: HttpRequest, dataset_type: str, dataset_id: str):
    """
    helper function to hide actual connection in the database but make publishing straight forward.
    """
    allowed_dataset_types = ["raster", "vector", "custom"]
    ogc_server = insert_internal_ogc_server(request)
    if dataset_type not in allowed_dataset_types:
        return HttpResponseNotFound()
    if dataset_type == "raster":
        published_as_wms = PublishedAsLayerWms(
            raster_dataset=RasterDataSet.objects.filter(id=dataset_id)[0]
        )
    elif dataset_type == "vector":
        published_as_wms = PublishedAsLayerWms(
            vector_dataset=VectorDataSet.objects.filter(id=dataset_id)[0]
        )
    elif dataset_type == "custom":
        published_as_wms = PublishedAsLayerWms(
            custom_dataset=CustomDataSet.objects.filter(id=dataset_id)[0]
        )
    else:
        return HttpResponseNotFound()
    published_as_wms.ogc_server = ogc_server.name
    published_as_wms.save()
    return redirect("admin:webgis_publishedaslayerwms_changelist")

assemble_tree_to_treebeard(children, current_parent, theme, project, geoportal_config, current_ogc_server=None)

Source code in src/georama/webgis/views.py
 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
181
182
183
184
185
186
187
188
189
190
191
192
193
def assemble_tree_to_treebeard(
    children: list[LayerGroup | WmsLayer | WmtsLayer],
    current_parent: LayerGroupMp,
    theme: PublishedAsTheme,
    project: Project,
    geoportal_config: ThemesJson,
    current_ogc_server: str | None = None,
):
    for child in children:
        node = current_parent.add_child(name=child.name)
        db_node = LayerGroupMp.objects.get(pk=node.pk)
        db_node.theme = theme
        db_node.themes_json_id = child.id
        db_node.save()
        if isinstance(child, LayerGroup):
            if hasattr(child, "ogcServer"):
                if child.ogcServer is not None:
                    current_ogc_server = child.ogcServer
                    logging.debug(f"set current_ogc_server by group: {current_ogc_server}")
                else:
                    logging.debug(
                        "New nested group but we leave ogc server because it was not redefined"
                    )
            db_node.metadata = DictEncoder().encode(child.metadata)
            db_node.mixed = child.mixed
            db_node.ogc_server = current_ogc_server
            db_node.dimensions = DictEncoder().encode(child.dimensions)

            db_node.save()
            assemble_tree_to_treebeard(
                child.children, db_node, theme, project, geoportal_config, current_ogc_server
            )
        else:
            if isinstance(child, WmsLayer):
                if child.ogcServer is None and current_ogc_server is not None:
                    child.ogcServer = current_ogc_server
                ogc_server = geoportal_config.get_ogc_server_by_name(child.ogcServer)
                query = RasterDataSet.objects.filter(project=project, name=child.name)
                if query.exists():
                    dataset = query.get()
                else:
                    source = WmsSource(
                        # TODO: This comes from QGIS and seem to bool if legend is shown or not, we need to know
                        #  how this transports to geogirafe
                        contextual_wms_legend="0",
                        # TODO: This we should make configurable or read it from capabilities of OGC Server
                        crs="EPSG:2056",
                        # TODO: This is normally a QGIS/Client specific thing, probably we can remove it from the
                        #  dataclass
                        dpi_mode="",
                        # TODO: Find why, how this is possible to fill
                        feature_count=0,
                        format=child.imageType,
                        layers=child.layers,
                        url=ogc_server.url,
                    )
                    dataset = RasterDataSet(
                        project=project,
                        name=child.name,
                        # TODO: Fix this to correct title (via translation?)
                        title=child.name.title(),
                        # TODO: should we fetch this from capabilities?
                        bbox="0,0,0,4000000,4000000,4000000",
                        # TODO: should we fetch this from capabilities?
                        bbox_wgs84="-90.0,-180.0,0.0,90.0,180.0,10000",
                        path=geoportal_config.get_ogc_server_by_name(child.ogcServer).url,
                        style="",
                        # this is wms for WMTS & WMS since (that comes from QGIS which handle both through
                        #   the same driver)
                        driver="wms",
                        source=DictEncoder().encode(source),
                        qgis_layer_id=child.id,
                        # TODO: should we fetch this from capabilities?
                        crs=DictEncoder().encode(Crs()),
                    )
                    dataset.save()
                PublishedAsLayerWms(
                    ogc_server=ogc_server.name,
                    themes_json_id=child.id,
                    name=dataset.name,
                    title=dataset.title,
                    metadata=DictEncoder().encode(child.metadata),
                    dataset=dataset,
                    layer_group=db_node,
                    min_resolution_hint=child.minResolutionHint,
                    max_resolution_hint=child.maxResolutionHint,
                    child_layers=DictEncoder().encode(child.childLayers),
                    dimensions=DictEncoder().encode(child.dimensions),
                ).save()
            elif isinstance(child, WmtsLayer):
                query = RasterDataSet.objects.filter(project=project, name=child.name)
                if query.exists():
                    dataset = query.get()
                else:
                    dataset = RasterDataSet(
                        project=project,
                        name=child.name,
                        # TODO: Fix this to correct title (via translation?)
                        title=child.name.title(),
                        # TODO: should we fetch this from capabilities?
                        bbox="0,0,0,4000000,4000000,4000000",
                        # TODO: should we fetch this from capabilities?
                        bbox_wgs84="-90.0,-180.0,0.0,90.0,180.0,10000",
                        path=child.url,
                        style="",
                        # this is wms for WMTS & WMS since (that comes from QGIS which handle both through
                        #   the same driver)
                        driver="wms",
                        source=DictEncoder().encode(
                            WmtsSource(
                                url=child.url,
                                layers=child.layer,
                                format=child.imageType,
                                contextual_wms_legend="0",
                                styles="default",
                                dpi_mode="7",
                                feature_count=10,
                                tile_dimensions="",
                                tile_matrix_set="",
                                crs="",
                                tile_pixel_ratio="0",
                            )
                        ),
                        qgis_layer_id=child.id,
                        # TODO: should we fetch this from capabilities?
                        crs=DictEncoder().encode(Crs()),
                    )
                    dataset.save()
                PublishedAsLayerWmts(
                    themes_json_id=child.id,
                    name=dataset.name,
                    title=dataset.title,
                    metadata=DictEncoder().encode(child.metadata),
                    dataset=dataset,
                    layer_group=db_node,
                    dimensions=DictEncoder().encode(child.dimensions),
                ).save()
            else:
                raise NotImplementedError(
                    f"Layer type is not implemented: {child.__class__.__name__}"
                )

home(request)

Source code in src/georama/webgis/views.py
47
48
49
50
def home(request):
    form = HomeForm()

    return render(request, "webgis.html", {"form": form})

insert_internal_ogc_server(request)

Checks if internal OGC server was already added. If it was added, it returns the DB entity if it was not added, it adds it and returns the added one.

Parameters:

Name Type Description Default
request HttpRequest

Django request as it comes from framework request.

required

Returns:

Type Description
OgcServer

The ogc server db entity or None if a more then one match was found (that would be an error).

Raises: AttributeError: If more than one OGC-Server was found with the name.

Source code in src/georama/webgis/views.py
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
def insert_internal_ogc_server(request: HttpRequest) -> WebGisOgcServer:
    """
    Checks if internal OGC server was already added. If it was added, it returns the DB entity
    if it was not added, it adds it and returns the added one.

    Args:
        request: Django request as it comes from framework request.

    Returns:
        The ogc server db entity or None if a more then one match was found (that would be an error).
    Raises:
        AttributeError: If more than one OGC-Server was found with the name.
    """
    webgis_ogc_server_name = "georama.webgis"
    url = f'{request.build_absolute_uri("/webgis")}/maps?'
    ogc_servers = WebGisOgcServer.objects.filter(name=webgis_ogc_server_name).all()
    if len(ogc_servers) == 0:
        ogc_server = WebGisOgcServer(
            url=url,
            url_wfs=url,
            type=webgis_ogc_server_name,
            credential=False,
            image_type="image/png",
            wfs_support=True,
            is_single_tile=False,
            namespace="https://www.opengis.ch/georama",
            name=webgis_ogc_server_name,
            description="The Georama OGC Server which publishes "
            "all configured WebGIS Layers.",
            attributes={},
        )
        ogc_server.save()
    elif len(ogc_servers) == 1:
        ogc_server = ogc_servers[0]
    else:
        logging.error(f"More than one OGC-Server was found for name {webgis_ogc_server_name}")
        raise AttributeError()
    return ogc_server

translation_json(request)

Source code in src/georama/webgis/views.py
596
597
598
599
600
601
602
603
604
605
606
def translation_json(request: HttpRequest):
    translation = {"de": {}}
    for layer_group in LayerGroupMp.objects.all():
        translation["de"][layer_group.name] = layer_group.title
    for theme in PublishedAsTheme.objects.all():
        translation["de"][theme.name] = theme.title
    for layer in PublishedAsLayerWms.objects.all():
        translation["de"][layer.name] = layer.title
    return HttpResponse(
        json.dumps(translation, indent=2), status=200, content_type="application/json"
    )