Skip to content

📘 API Reference Data Integration

Georama Data Integration

admin

CustomDataSetAdmin

Bases: DataSetAdmin

Source code in src/georama/data_integration/admin.py
260
261
class CustomDataSetAdmin(DataSetAdmin):
    pass

DataSetAdmin

Bases: ModelAdmin

Source code in src/georama/data_integration/admin.py
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
class DataSetAdmin(admin.ModelAdmin):
    list_display = ["name"]
    fields = [
        "name",
        "title",
        "bbox",
        "minimum_scale",
        "maximum_scale",
        "source_detail",
        "crs_detail",
        "path",
        "driver",
    ]

    readonly_fields = [
        "name",
        "title",
        "bbox",
        "source_detail",
        "crs_detail",
        "path",
        "driver",
    ]

    def source_detail(self, obj):
        snippet_parts = ["<ul>"]
        for key in obj.source:
            snippet_parts.append(
                f'<li><label>{key}</label> → <span class="badge badge-secondary">{obj.source[key]}</span></li>'
            )
        snippet_parts.append("</ul>")
        return mark_safe("".join(snippet_parts))

    source_detail.short_description = "Source"

    def crs_detail(self, obj):
        snippet_parts = ["<ul>"]
        for key in obj.crs:
            snippet_parts.append(
                f'<li><label>{key}</label> → <span class="badge badge-secondary">{obj.crs[key]}</span></li>'
            )
        snippet_parts.append("</ul>")
        return mark_safe("".join(snippet_parts))

    crs_detail.short_description = "Crs"

fields = ['name', 'title', 'bbox', 'minimum_scale', 'maximum_scale', 'source_detail', 'crs_detail', 'path', 'driver'] class-attribute instance-attribute

list_display = ['name'] class-attribute instance-attribute

readonly_fields = ['name', 'title', 'bbox', 'source_detail', 'crs_detail', 'path', 'driver'] class-attribute instance-attribute

crs_detail(obj)

Source code in src/georama/data_integration/admin.py
243
244
245
246
247
248
249
250
def crs_detail(self, obj):
    snippet_parts = ["<ul>"]
    for key in obj.crs:
        snippet_parts.append(
            f'<li><label>{key}</label> → <span class="badge badge-secondary">{obj.crs[key]}</span></li>'
        )
    snippet_parts.append("</ul>")
    return mark_safe("".join(snippet_parts))

source_detail(obj)

Source code in src/georama/data_integration/admin.py
232
233
234
235
236
237
238
239
def source_detail(self, obj):
    snippet_parts = ["<ul>"]
    for key in obj.source:
        snippet_parts.append(
            f'<li><label>{key}</label> → <span class="badge badge-secondary">{obj.source[key]}</span></li>'
        )
    snippet_parts.append("</ul>")
    return mark_safe("".join(snippet_parts))

MandantAdmin

Bases: ModelAdmin

Source code in src/georama/data_integration/admin.py
295
296
class MandantAdmin(admin.ModelAdmin):
    pass

ProjectAdmin

Bases: ModelAdmin

Source code in src/georama/data_integration/admin.py
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
class ProjectAdmin(admin.ModelAdmin):
    list_display = [
        "name",
        "mandant_name",
        "vector_dataset_count",
        "raster_dataset_count",
        "custom_dataset_count",
        "project_file_uptodate",
    ]

    def vector_dataset_count(self, obj):
        return obj.vector_datasets.count()

    vector_dataset_count.admin_order_field = "vector_dataset_count"
    vector_dataset_count.short_description = "Vector Datasets"

    def raster_dataset_count(self, obj):
        return obj.raster_datasets.count()

    raster_dataset_count.admin_order_field = "raster_dataset_count"
    raster_dataset_count.short_description = "Raster Datasets"

    def custom_dataset_count(self, obj):
        return obj.custom_datasets.count()

    custom_dataset_count.admin_order_field = "custom_dataset_count"
    custom_dataset_count.short_description = "Custom Datasets"

    def project_file_uptodate(self, obj: Project):
        try:
            config = Config()
            qpfs = QgisProjectFileStructure(config.path)
            qpfs.create_groups(config.qgis_project_extensions)
            group = qpfs.find_group_by_name(obj.mandant.name)
            project = group.find_project_by_name(obj.name)
            return mark_safe("&check;") if obj.hash == project.hash else ""
        except Exception as e:
            logging.error(f"Chould not check project status. Original Error: {e}")
            return ""

    project_file_uptodate.admin_order_field = "project_file_uptodate"
    project_file_uptodate.short_description = "Project File uptodate"

    def mandant_name(self, obj: Project):
        # TODO: make this a link to the dedicated mandant instance details
        return obj.mandant.name

    mandant_name.admin_order_field = "project_mandant_name"
    mandant_name.short_description = "Project Mandant Name"

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

    def qgis_projects(self, request: HttpRequest, extra_context=None):
        config = Config()
        qgis_project_file_structure = QgisProjectFileStructure(os.path.join(config.path))
        qgis_project_file_structure.create_groups(config.qgis_project_extensions)

        context = dict(
            # Include common variables for rendering the admin template.
            self.admin_site.each_context(request),
            # Anything else you want in the context...
            qgis_project_file_structure=qgis_project_file_structure,
        )
        return TemplateResponse(
            request, "admin/data_integration/project/qgis_projects.html", context
        )

    def get_readonly_fields(self, request, obj=None):
        return ["integration_date", "hash"]

list_display = ['name', 'mandant_name', 'vector_dataset_count', 'raster_dataset_count', 'custom_dataset_count', 'project_file_uptodate'] class-attribute instance-attribute

custom_dataset_count(obj)

Source code in src/georama/data_integration/admin.py
150
151
def custom_dataset_count(self, obj):
    return obj.custom_datasets.count()

get_readonly_fields(request, obj=None)

Source code in src/georama/data_integration/admin.py
204
205
def get_readonly_fields(self, request, obj=None):
    return ["integration_date", "hash"]

get_urls()

Source code in src/georama/data_integration/admin.py
178
179
180
181
182
183
184
185
186
187
def get_urls(self):
    urls = super().get_urls()
    my_urls = [
        path(
            "qgis_projects/",
            self.admin_site.admin_view(self.qgis_projects),
            name="qgis_projects",
        )
    ]
    return my_urls + urls

mandant_name(obj)

Source code in src/georama/data_integration/admin.py
171
172
173
def mandant_name(self, obj: Project):
    # TODO: make this a link to the dedicated mandant instance details
    return obj.mandant.name

project_file_uptodate(obj)

Source code in src/georama/data_integration/admin.py
156
157
158
159
160
161
162
163
164
165
166
def project_file_uptodate(self, obj: Project):
    try:
        config = Config()
        qpfs = QgisProjectFileStructure(config.path)
        qpfs.create_groups(config.qgis_project_extensions)
        group = qpfs.find_group_by_name(obj.mandant.name)
        project = group.find_project_by_name(obj.name)
        return mark_safe("&check;") if obj.hash == project.hash else ""
    except Exception as e:
        logging.error(f"Chould not check project status. Original Error: {e}")
        return ""

qgis_projects(request, extra_context=None)

Source code in src/georama/data_integration/admin.py
189
190
191
192
193
194
195
196
197
198
199
200
201
202
def qgis_projects(self, request: HttpRequest, extra_context=None):
    config = Config()
    qgis_project_file_structure = QgisProjectFileStructure(os.path.join(config.path))
    qgis_project_file_structure.create_groups(config.qgis_project_extensions)

    context = dict(
        # Include common variables for rendering the admin template.
        self.admin_site.each_context(request),
        # Anything else you want in the context...
        qgis_project_file_structure=qgis_project_file_structure,
    )
    return TemplateResponse(
        request, "admin/data_integration/project/qgis_projects.html", context
    )

raster_dataset_count(obj)

Source code in src/georama/data_integration/admin.py
144
145
def raster_dataset_count(self, obj):
    return obj.raster_datasets.count()

vector_dataset_count(obj)

Source code in src/georama/data_integration/admin.py
138
139
def vector_dataset_count(self, obj):
    return obj.vector_datasets.count()

QgisProject dataclass

Source code in src/georama/data_integration/admin.py
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
@dataclass
class QgisProject:
    parent: "QgisProjectGroup"
    name: str
    suffix: str

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

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

    @property
    def config_path(self) -> str:
        return os.path.join(
            self.parent.parent.path, self.parent.name, self.qualified_config_name
        )

    @property
    def project_path(self) -> str:
        return os.path.join(
            self.parent.parent.path, self.parent.name, self.qualified_project_name
        )

    @property
    def has_config(self) -> bool:
        return os.path.isfile(self.config_path)

    @property
    def hash(self) -> str:
        if self.has_config:
            with open(self.config_path, mode="rb") as cf:
                return hashlib.md5(cf.read()).hexdigest()

config_path property

has_config property

hash property

name instance-attribute

parent instance-attribute

project_path property

qualified_config_name property

qualified_project_name property

suffix instance-attribute

__init__(parent, name, suffix)

QgisProjectFileStructure dataclass

Source code in src/georama/data_integration/admin.py
 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
@dataclass
class QgisProjectFileStructure:
    path: str
    groups: list[QgisProjectGroup] = field(default_factory=list)

    def is_dir(self, name) -> bool:
        return os.path.isdir(os.path.join(self.path, name))

    def dirs(self) -> list[str]:
        dirs = []
        for name in os.listdir(self.path):
            dir_path = os.path.join(self.path, name)
            if os.path.isdir(dir_path):
                dirs.append(name)
            else:
                pass
        return dirs

    def create_groups(self, allowed_extensions: list[str]):
        for name in self.dirs():
            group = QgisProjectGroup(parent=self, name=name)
            group.create_projects(allowed_extensions=allowed_extensions)
            self.groups.append(group)

    def find_group_by_name(self, name) -> QgisProjectGroup | None:
        for group in self.groups:
            if group.name == name:
                return group

groups = field(default_factory=list) class-attribute instance-attribute

path instance-attribute

__init__(path, groups=list())

create_groups(allowed_extensions)

Source code in src/georama/data_integration/admin.py
116
117
118
119
120
def create_groups(self, allowed_extensions: list[str]):
    for name in self.dirs():
        group = QgisProjectGroup(parent=self, name=name)
        group.create_projects(allowed_extensions=allowed_extensions)
        self.groups.append(group)

dirs()

Source code in src/georama/data_integration/admin.py
106
107
108
109
110
111
112
113
114
def dirs(self) -> list[str]:
    dirs = []
    for name in os.listdir(self.path):
        dir_path = os.path.join(self.path, name)
        if os.path.isdir(dir_path):
            dirs.append(name)
        else:
            pass
    return dirs

find_group_by_name(name)

Source code in src/georama/data_integration/admin.py
122
123
124
125
def find_group_by_name(self, name) -> QgisProjectGroup | None:
    for group in self.groups:
        if group.name == name:
            return group

is_dir(name)

Source code in src/georama/data_integration/admin.py
103
104
def is_dir(self, name) -> bool:
    return os.path.isdir(os.path.join(self.path, name))

QgisProjectGroup dataclass

Source code in src/georama/data_integration/admin.py
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
@dataclass
class QgisProjectGroup:
    parent: "QgisProjectFileStructure"
    name: str
    projects: list[QgisProject] = field(default_factory=list)

    @property
    def project_paths(self) -> list[str]:
        return [project.project_path for project in self.projects]

    @property
    def config_paths(self) -> list[str]:
        return [project.config_path for project in self.projects]

    @property
    def path(self) -> str:
        return os.path.join(self.parent.path, self.name)

    def is_file(self, name) -> bool:
        return os.path.isfile(os.path.join(self.path, name))

    def create_projects(self, allowed_extensions: list[str]):
        for name in os.listdir(self.path):
            if self.is_file(name):
                project_file_name = Path(name).stem
                project_file_suffix = name.replace(project_file_name, "")
                if project_file_suffix in allowed_extensions:
                    project = QgisProject(
                        parent=self, name=project_file_name, suffix=project_file_suffix
                    )
                    self.projects.append(project)

    def find_project_by_name(self, name) -> QgisProject | None:
        for project in self.projects:
            if project.name == name:
                return project

config_paths property

name instance-attribute

parent instance-attribute

path property

project_paths property

projects = field(default_factory=list) class-attribute instance-attribute

__init__(parent, name, projects=list())

create_projects(allowed_extensions)

Source code in src/georama/data_integration/admin.py
81
82
83
84
85
86
87
88
89
90
def create_projects(self, allowed_extensions: list[str]):
    for name in os.listdir(self.path):
        if self.is_file(name):
            project_file_name = Path(name).stem
            project_file_suffix = name.replace(project_file_name, "")
            if project_file_suffix in allowed_extensions:
                project = QgisProject(
                    parent=self, name=project_file_name, suffix=project_file_suffix
                )
                self.projects.append(project)

find_project_by_name(name)

Source code in src/georama/data_integration/admin.py
92
93
94
95
def find_project_by_name(self, name) -> QgisProject | None:
    for project in self.projects:
        if project.name == name:
            return project

is_file(name)

Source code in src/georama/data_integration/admin.py
78
79
def is_file(self, name) -> bool:
    return os.path.isfile(os.path.join(self.path, name))

RasterDataSetAdmin

Bases: DataSetAdmin

Source code in src/georama/data_integration/admin.py
255
256
257
class RasterDataSetAdmin(DataSetAdmin):

    pass

VectorDataSetAdmin

Bases: DataSetAdmin

Source code in src/georama/data_integration/admin.py
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
class VectorDataSetAdmin(DataSetAdmin):
    list_display = ["name", "mandant_name", "project_name", "field_count"]
    fields = DataSetAdmin.fields + ["fields_detail"]
    readonly_fields = DataSetAdmin.fields + ["fields_detail"]

    def mandant_name(self, obj: VectorDataSet):
        return obj.project.mandant.name

    def project_name(self, obj: VectorDataSet):
        return obj.project.name

    def fields_detail(self, obj: VectorDataSet):
        snippet_parts = ["<ul>"]
        for field in obj.fields.all():
            snippet_parts.append(
                f'<li><label>{field.name}</label> → <span class="badge badge-secondary">{field.type}</span></li>'
            )
        snippet_parts.append("</ul>")
        return mark_safe("".join(snippet_parts))

    fields_detail.short_description = "Fields"

    def field_count(self, obj):
        return mark_safe(
            '<span class="badge badge-secondary">{}</span>'.format(obj.fields.count())
        )

    field_count.admin_order_field = "field_count"
    field_count.short_description = "Fields"

fields = DataSetAdmin.fields + ['fields_detail'] class-attribute instance-attribute

list_display = ['name', 'mandant_name', 'project_name', 'field_count'] class-attribute instance-attribute

readonly_fields = DataSetAdmin.fields + ['fields_detail'] class-attribute instance-attribute

field_count(obj)

Source code in src/georama/data_integration/admin.py
286
287
288
289
def field_count(self, obj):
    return mark_safe(
        '<span class="badge badge-secondary">{}</span>'.format(obj.fields.count())
    )

fields_detail(obj)

Source code in src/georama/data_integration/admin.py
275
276
277
278
279
280
281
282
def fields_detail(self, obj: VectorDataSet):
    snippet_parts = ["<ul>"]
    for field in obj.fields.all():
        snippet_parts.append(
            f'<li><label>{field.name}</label> → <span class="badge badge-secondary">{field.type}</span></li>'
        )
    snippet_parts.append("</ul>")
    return mark_safe("".join(snippet_parts))

mandant_name(obj)

Source code in src/georama/data_integration/admin.py
269
270
def mandant_name(self, obj: VectorDataSet):
    return obj.project.mandant.name

project_name(obj)

Source code in src/georama/data_integration/admin.py
272
273
def project_name(self, obj: VectorDataSet):
    return obj.project.name

apps

QmeleonConfig

Bases: AppConfig

Source code in src/georama/data_integration/apps.py
4
5
6
7
class QmeleonConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "georama.data_integration"
    verbose_name = "Data Integration"

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

name = 'georama.data_integration' class-attribute instance-attribute

verbose_name = 'Data Integration' class-attribute instance-attribute

data_integration_config

Config

Source code in src/georama/data_integration/data_integration_config.py
 4
 5
 6
 7
 8
 9
10
11
class Config:
    @property
    def path(self) -> str:
        return os.path.join(os.environ.get("GEORAMA_DATA_INTEGRATION_ROOT", "/io/data"))

    @property
    def qgis_project_extensions(self) -> list[str]:
        return [".qgz", ".qgs"]

path property

qgis_project_extensions property

migrations

0001_initial

Migration

Bases: Migration

Source code in src/georama/data_integration/migrations/0001_initial.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
class Migration(migrations.Migration):

    initial = True

    dependencies = []

    operations = [
        migrations.CreateModel(
            name="Project",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField(max_length=1000, unique=True)),
                ("title", models.CharField(max_length=1000)),
                ("version", models.CharField(max_length=1000)),
            ],
        ),
        migrations.CreateModel(
            name="DataSet",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField(max_length=1000, unique=True)),
                ("title", models.CharField(max_length=1000)),
                ("bbox", models.CharField(max_length=1000)),
                ("path", models.CharField(max_length=10000)),
                ("style", models.TextField()),
                ("driver", models.CharField(max_length=50)),
                ("type", models.CharField(max_length=50)),
                (
                    "project",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="datasets",
                        related_query_name="dataset",
                        to="data_integration.project",
                    ),
                ),
            ],
        ),
    ]
dependencies = [] class-attribute instance-attribute
initial = True class-attribute instance-attribute
operations = [migrations.CreateModel(name='Project', fields=[('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=1000, unique=True)), ('title', models.CharField(max_length=1000)), ('version', models.CharField(max_length=1000))]), migrations.CreateModel(name='DataSet', fields=[('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=1000, unique=True)), ('title', models.CharField(max_length=1000)), ('bbox', models.CharField(max_length=1000)), ('path', models.CharField(max_length=10000)), ('style', models.TextField()), ('driver', models.CharField(max_length=50)), ('type', models.CharField(max_length=50)), ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='datasets', related_query_name='dataset', to='data_integration.project'))])] class-attribute instance-attribute

0002_alter_project_unique_together

Migration

Bases: Migration

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

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

    operations = [
        migrations.AlterUniqueTogether(
            name="project",
            unique_together={("name", "version")},
        ),
    ]
dependencies = [('data_integration', '0001_initial')] class-attribute instance-attribute
operations = [migrations.AlterUniqueTogether(name='project', unique_together={('name', 'version')})] class-attribute instance-attribute

0003_rasterdataset_vectordataset_field_delete_dataset

Migration

Bases: Migration

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

    dependencies = [
        ("data_integration", "0002_alter_project_unique_together"),
    ]

    operations = [
        migrations.CreateModel(
            name="RasterDataSet",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField(max_length=1000, unique=True)),
                ("title", models.CharField(max_length=1000)),
                ("bbox", models.CharField(max_length=1000)),
                ("path", models.CharField(max_length=10000)),
                ("style", models.TextField()),
                ("driver", models.CharField(max_length=50)),
                (
                    "project",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="raster_datasets",
                        related_query_name="raster_dataset",
                        to="data_integration.project",
                    ),
                ),
            ],
            options={
                "abstract": False,
            },
        ),
        migrations.CreateModel(
            name="VectorDataSet",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField(max_length=1000, unique=True)),
                ("title", models.CharField(max_length=1000)),
                ("bbox", models.CharField(max_length=1000)),
                ("path", models.CharField(max_length=10000)),
                ("style", models.TextField()),
                ("driver", models.CharField(max_length=50)),
                (
                    "project",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="vector_datasets",
                        related_query_name="vector_dataset",
                        to="data_integration.project",
                    ),
                ),
            ],
            options={
                "abstract": False,
            },
        ),
        migrations.CreateModel(
            name="Field",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField(max_length=1000)),
                ("type", models.CharField(max_length=1000)),
                (
                    "vector_dataset",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="fields",
                        related_query_name="field",
                        to="data_integration.vectordataset",
                    ),
                ),
            ],
        ),
        migrations.DeleteModel(
            name="DataSet",
        ),
    ]
dependencies = [('data_integration', '0002_alter_project_unique_together')] class-attribute instance-attribute
operations = [migrations.CreateModel(name='RasterDataSet', fields=[('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=1000, unique=True)), ('title', models.CharField(max_length=1000)), ('bbox', models.CharField(max_length=1000)), ('path', models.CharField(max_length=10000)), ('style', models.TextField()), ('driver', models.CharField(max_length=50)), ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='raster_datasets', related_query_name='raster_dataset', to='data_integration.project'))], options={'abstract': False}), migrations.CreateModel(name='VectorDataSet', fields=[('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=1000, unique=True)), ('title', models.CharField(max_length=1000)), ('bbox', models.CharField(max_length=1000)), ('path', models.CharField(max_length=10000)), ('style', models.TextField()), ('driver', models.CharField(max_length=50)), ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='vector_datasets', related_query_name='vector_dataset', to='data_integration.project'))], options={'abstract': False}), migrations.CreateModel(name='Field', fields=[('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=1000)), ('type', models.CharField(max_length=1000)), ('vector_dataset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fields', related_query_name='field', to='data_integration.vectordataset'))]), migrations.DeleteModel(name='DataSet')] class-attribute instance-attribute

0004_alter_field_unique_together_and_more

Migration

Bases: Migration

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

    dependencies = [
        ("data_integration", "0003_rasterdataset_vectordataset_field_delete_dataset"),
    ]

    operations = [
        migrations.AlterUniqueTogether(
            name="field",
            unique_together={("name", "vector_dataset")},
        ),
        migrations.AlterUniqueTogether(
            name="rasterdataset",
            unique_together={("name", "project")},
        ),
        migrations.AlterUniqueTogether(
            name="vectordataset",
            unique_together={("name", "project")},
        ),
    ]
dependencies = [('data_integration', '0003_rasterdataset_vectordataset_field_delete_dataset')] class-attribute instance-attribute
operations = [migrations.AlterUniqueTogether(name='field', unique_together={('name', 'vector_dataset')}), migrations.AlterUniqueTogether(name='rasterdataset', unique_together={('name', 'project')}), migrations.AlterUniqueTogether(name='vectordataset', unique_together={('name', 'project')})] class-attribute instance-attribute

0005_rasterdataset_source_vectordataset_source

Migration

Bases: Migration

Source code in src/georama/data_integration/migrations/0005_rasterdataset_source_vectordataset_source.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Migration(migrations.Migration):

    dependencies = [
        ("data_integration", "0004_alter_field_unique_together_and_more"),
    ]

    operations = [
        migrations.AddField(
            model_name="rasterdataset",
            name="source",
            field=models.JSONField(default=dict),
        ),
        migrations.AddField(
            model_name="vectordataset",
            name="source",
            field=models.JSONField(default=dict),
        ),
    ]
dependencies = [('data_integration', '0004_alter_field_unique_together_and_more')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='rasterdataset', name='source', field=models.JSONField(default=dict)), migrations.AddField(model_name='vectordataset', name='source', field=models.JSONField(default=dict))] class-attribute instance-attribute

0006_project_hash

Migration

Bases: Migration

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

    dependencies = [
        ("data_integration", "0005_rasterdataset_source_vectordataset_source"),
    ]

    operations = [
        migrations.AddField(
            model_name="project",
            name="hash",
            field=models.CharField(blank=True, max_length=20000, null=True),
        ),
    ]
dependencies = [('data_integration', '0005_rasterdataset_source_vectordataset_source')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='project', name='hash', field=models.CharField(blank=True, max_length=20000, null=True))] class-attribute instance-attribute

0007_alter_project_unique_together_project_group_and_more

Migration

Bases: Migration

Source code in src/georama/data_integration/migrations/0007_alter_project_unique_together_project_group_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 = [
        ("data_integration", "0006_project_hash"),
    ]

    operations = [
        migrations.AlterUniqueTogether(
            name="project",
            unique_together=set(),
        ),
        migrations.AddField(
            model_name="project",
            name="group",
            field=models.CharField(max_length=1000, null=True),
        ),
        migrations.AddField(
            model_name="project",
            name="integration_date",
            field=models.DateTimeField(default=datetime.datetime.now),
        ),
        migrations.AlterUniqueTogether(
            name="project",
            unique_together={("name", "version", "group")},
        ),
    ]
dependencies = [('data_integration', '0006_project_hash')] class-attribute instance-attribute
operations = [migrations.AlterUniqueTogether(name='project', unique_together=set()), migrations.AddField(model_name='project', name='group', field=models.CharField(max_length=1000, null=True)), migrations.AddField(model_name='project', name='integration_date', field=models.DateTimeField(default=datetime.datetime.now)), migrations.AlterUniqueTogether(name='project', unique_together={('name', 'version', 'group')})] class-attribute instance-attribute

0008_alter_project_name

Migration

Bases: Migration

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

    dependencies = [
        ("data_integration", "0007_alter_project_unique_together_project_group_and_more"),
    ]

    operations = [
        migrations.AlterField(
            model_name="project",
            name="name",
            field=models.CharField(max_length=1000),
        ),
    ]
dependencies = [('data_integration', '0007_alter_project_unique_together_project_group_and_more')] class-attribute instance-attribute
operations = [migrations.AlterField(model_name='project', name='name', field=models.CharField(max_length=1000))] class-attribute instance-attribute

0009_alter_rasterdataset_name_alter_vectordataset_name

Migration

Bases: Migration

Source code in src/georama/data_integration/migrations/0009_alter_rasterdataset_name_alter_vectordataset_name.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Migration(migrations.Migration):

    dependencies = [
        ("data_integration", "0008_alter_project_name"),
    ]

    operations = [
        migrations.AlterField(
            model_name="rasterdataset",
            name="name",
            field=models.CharField(max_length=1000),
        ),
        migrations.AlterField(
            model_name="vectordataset",
            name="name",
            field=models.CharField(max_length=1000),
        ),
    ]
dependencies = [('data_integration', '0008_alter_project_name')] class-attribute instance-attribute
operations = [migrations.AlterField(model_name='rasterdataset', name='name', field=models.CharField(max_length=1000)), migrations.AlterField(model_name='vectordataset', name='name', field=models.CharField(max_length=1000))] class-attribute instance-attribute

0010_rasterdataset_qgis_layer_id_and_more

Migration

Bases: Migration

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

    dependencies = [
        ("data_integration", "0009_alter_rasterdataset_name_alter_vectordataset_name"),
    ]

    operations = [
        migrations.AddField(
            model_name="rasterdataset",
            name="qgis_layer_id",
            field=models.CharField(default="intermediate", max_length=1000),
            preserve_default=False,
        ),
        migrations.AddField(
            model_name="vectordataset",
            name="qgis_layer_id",
            field=models.CharField(default="intermediate", max_length=1000),
            preserve_default=False,
        ),
    ]
dependencies = [('data_integration', '0009_alter_rasterdataset_name_alter_vectordataset_name')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='rasterdataset', name='qgis_layer_id', field=models.CharField(default='intermediate', max_length=1000), preserve_default=False), migrations.AddField(model_name='vectordataset', name='qgis_layer_id', field=models.CharField(default='intermediate', max_length=1000), preserve_default=False)] class-attribute instance-attribute

0011_rasterdataset_crs_vectordataset_crs

Migration

Bases: Migration

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

    dependencies = [
        ("data_integration", "0010_rasterdataset_qgis_layer_id_and_more"),
    ]

    operations = [
        migrations.AddField(
            model_name="rasterdataset",
            name="crs",
            field=models.JSONField(default=dict),
        ),
        migrations.AddField(
            model_name="vectordataset",
            name="crs",
            field=models.JSONField(default=dict),
        ),
    ]
dependencies = [('data_integration', '0010_rasterdataset_qgis_layer_id_and_more')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='rasterdataset', name='crs', field=models.JSONField(default=dict)), migrations.AddField(model_name='vectordataset', name='crs', field=models.JSONField(default=dict))] class-attribute instance-attribute

0012_rasterdataset_bbox_wgs84_vectordataset_bbox_wgs84

Migration

Bases: Migration

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

    dependencies = [
        ("data_integration", "0011_rasterdataset_crs_vectordataset_crs"),
    ]

    operations = [
        migrations.AddField(
            model_name="rasterdataset",
            name="bbox_wgs84",
            field=models.CharField(default="0,0,0,0", max_length=1000),
            preserve_default=False,
        ),
        migrations.AddField(
            model_name="vectordataset",
            name="bbox_wgs84",
            field=models.CharField(default="0,0,0,0", max_length=1000),
            preserve_default=False,
        ),
    ]
dependencies = [('data_integration', '0011_rasterdataset_crs_vectordataset_crs')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='rasterdataset', name='bbox_wgs84', field=models.CharField(default='0,0,0,0', max_length=1000), preserve_default=False), migrations.AddField(model_name='vectordataset', name='bbox_wgs84', field=models.CharField(default='0,0,0,0', max_length=1000), preserve_default=False)] class-attribute instance-attribute

0013_customdataset

Migration

Bases: Migration

Source code in src/georama/data_integration/migrations/0013_customdataset.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
class Migration(migrations.Migration):

    dependencies = [
        ("data_integration", "0012_rasterdataset_bbox_wgs84_vectordataset_bbox_wgs84"),
    ]

    operations = [
        migrations.CreateModel(
            name="CustomDataSet",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField(max_length=1000)),
                ("qgis_layer_id", models.CharField(max_length=1000)),
                ("title", models.CharField(max_length=1000)),
                ("bbox", models.CharField(max_length=1000)),
                ("bbox_wgs84", models.CharField(max_length=1000)),
                ("path", models.CharField(max_length=10000)),
                ("source", models.JSONField(default=dict)),
                ("style", models.TextField()),
                ("driver", models.CharField(max_length=50)),
                ("crs", models.JSONField(default=dict)),
                (
                    "project",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="custom_datasets",
                        related_query_name="custom_dataset",
                        to="data_integration.project",
                    ),
                ),
            ],
            options={
                "unique_together": {("name", "project")},
            },
        ),
    ]
dependencies = [('data_integration', '0012_rasterdataset_bbox_wgs84_vectordataset_bbox_wgs84')] class-attribute instance-attribute
operations = [migrations.CreateModel(name='CustomDataSet', fields=[('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=1000)), ('qgis_layer_id', models.CharField(max_length=1000)), ('title', models.CharField(max_length=1000)), ('bbox', models.CharField(max_length=1000)), ('bbox_wgs84', models.CharField(max_length=1000)), ('path', models.CharField(max_length=10000)), ('source', models.JSONField(default=dict)), ('style', models.TextField()), ('driver', models.CharField(max_length=50)), ('crs', models.JSONField(default=dict)), ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='custom_datasets', related_query_name='custom_dataset', to='data_integration.project'))], options={'unique_together': {('name', 'project')}})] class-attribute instance-attribute

0014_mandant_alter_project_unique_together_and_more

Migration

Bases: Migration

Source code in src/georama/data_integration/migrations/0014_mandant_alter_project_unique_together_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
class Migration(migrations.Migration):

    dependencies = [
        ("data_integration", "0013_customdataset"),
    ]

    operations = [
        migrations.CreateModel(
            name="Mandant",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField(unique=True)),
            ],
        ),
        migrations.AlterUniqueTogether(
            name="project",
            unique_together=set(),
        ),
        migrations.AddField(
            model_name="project",
            name="mandant",
            field=models.ForeignKey(
                default=None,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="mandants",
                related_query_name="mandant",
                to="data_integration.mandant",
            ),
        ),
        migrations.AlterUniqueTogether(
            name="project",
            unique_together={("name", "version", "mandant")},
        ),
        migrations.RemoveField(
            model_name="project",
            name="group",
        ),
    ]
dependencies = [('data_integration', '0013_customdataset')] class-attribute instance-attribute
operations = [migrations.CreateModel(name='Mandant', fields=[('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(unique=True))]), migrations.AlterUniqueTogether(name='project', unique_together=set()), migrations.AddField(model_name='project', name='mandant', field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='mandants', related_query_name='mandant', to='data_integration.mandant')), migrations.AlterUniqueTogether(name='project', unique_together={('name', 'version', 'mandant')}), migrations.RemoveField(model_name='project', name='group')] class-attribute instance-attribute

0015_alter_project_mandant

Migration

Bases: Migration

Source code in src/georama/data_integration/migrations/0015_alter_project_mandant.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 = [
        ("data_integration", "0014_mandant_alter_project_unique_together_and_more"),
    ]

    operations = [
        migrations.AlterField(
            model_name="project",
            name="mandant",
            field=models.ForeignKey(
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name="mandants",
                related_query_name="mandant",
                to="data_integration.mandant",
            ),
        ),
    ]
dependencies = [('data_integration', '0014_mandant_alter_project_unique_together_and_more')] class-attribute instance-attribute
operations = [migrations.AlterField(model_name='project', name='mandant', field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mandants', related_query_name='mandant', to='data_integration.mandant'))] class-attribute instance-attribute

0016_mandant_description

Migration

Bases: Migration

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

    dependencies = [
        ("data_integration", "0015_alter_project_mandant"),
    ]

    operations = [
        migrations.AddField(
            model_name="mandant",
            name="description",
            field=models.TextField(null=True),
        ),
    ]
dependencies = [('data_integration', '0015_alter_project_mandant')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='mandant', name='description', field=models.TextField(null=True))] class-attribute instance-attribute

0017_customdataset_remote_rasterdataset_remote_and_more

Migration

Bases: Migration

Source code in src/georama/data_integration/migrations/0017_customdataset_remote_rasterdataset_remote_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
class Migration(migrations.Migration):

    dependencies = [
        ("data_integration", "0016_mandant_description"),
    ]

    operations = [
        migrations.AddField(
            model_name="customdataset",
            name="remote",
            field=models.BooleanField(default=False),
        ),
        migrations.AddField(
            model_name="rasterdataset",
            name="remote",
            field=models.BooleanField(default=False),
        ),
        migrations.AddField(
            model_name="vectordataset",
            name="remote",
            field=models.BooleanField(default=False),
        ),
    ]
dependencies = [('data_integration', '0016_mandant_description')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='customdataset', name='remote', field=models.BooleanField(default=False)), migrations.AddField(model_name='rasterdataset', name='remote', field=models.BooleanField(default=False)), migrations.AddField(model_name='vectordataset', name='remote', field=models.BooleanField(default=False))] class-attribute instance-attribute

0018_remove_customdataset_remote_and_more

Migration

Bases: Migration

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

    dependencies = [
        ("data_integration", "0017_customdataset_remote_rasterdataset_remote_and_more"),
    ]

    operations = [
        migrations.RemoveField(
            model_name="customdataset",
            name="remote",
        ),
        migrations.RemoveField(
            model_name="rasterdataset",
            name="remote",
        ),
        migrations.RemoveField(
            model_name="vectordataset",
            name="remote",
        ),
    ]
dependencies = [('data_integration', '0017_customdataset_remote_rasterdataset_remote_and_more')] class-attribute instance-attribute
operations = [migrations.RemoveField(model_name='customdataset', name='remote'), migrations.RemoveField(model_name='rasterdataset', name='remote'), migrations.RemoveField(model_name='vectordataset', name='remote')] class-attribute instance-attribute

0019_vectordataset_extent_buffer

Migration

Bases: Migration

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

    dependencies = [
        ("data_integration", "0018_remove_customdataset_remote_and_more"),
    ]

    operations = [
        migrations.AddField(
            model_name="vectordataset",
            name="extent_buffer",
            field=models.FloatField(default=0.0),
        ),
    ]
dependencies = [('data_integration', '0018_remove_customdataset_remote_and_more')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='vectordataset', name='extent_buffer', field=models.FloatField(default=0.0))] class-attribute instance-attribute

0020_remove_vectordataset_extent_buffer

Migration

Bases: Migration

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

    dependencies = [
        ("data_integration", "0019_vectordataset_extent_buffer"),
    ]

    operations = [
        migrations.RemoveField(
            model_name="vectordataset",
            name="extent_buffer",
        ),
    ]
dependencies = [('data_integration', '0019_vectordataset_extent_buffer')] class-attribute instance-attribute
operations = [migrations.RemoveField(model_name='vectordataset', name='extent_buffer')] class-attribute instance-attribute

0021_customdataset_maximum_scale_and_more

Migration

Bases: Migration

Source code in src/georama/data_integration/migrations/0021_customdataset_maximum_scale_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 = [
        ("data_integration", "0020_remove_vectordataset_extent_buffer"),
    ]

    operations = [
        migrations.AddField(
            model_name="customdataset",
            name="maximum_scale",
            field=models.FloatField(null=True),
        ),
        migrations.AddField(
            model_name="customdataset",
            name="minimum_scale",
            field=models.FloatField(null=True),
        ),
        migrations.AddField(
            model_name="rasterdataset",
            name="maximum_scale",
            field=models.FloatField(null=True),
        ),
        migrations.AddField(
            model_name="rasterdataset",
            name="minimum_scale",
            field=models.FloatField(null=True),
        ),
        migrations.AddField(
            model_name="vectordataset",
            name="maximum_scale",
            field=models.FloatField(null=True),
        ),
        migrations.AddField(
            model_name="vectordataset",
            name="minimum_scale",
            field=models.FloatField(null=True),
        ),
    ]
dependencies = [('data_integration', '0020_remove_vectordataset_extent_buffer')] class-attribute instance-attribute
operations = [migrations.AddField(model_name='customdataset', name='maximum_scale', field=models.FloatField(null=True)), migrations.AddField(model_name='customdataset', name='minimum_scale', field=models.FloatField(null=True)), migrations.AddField(model_name='rasterdataset', name='maximum_scale', field=models.FloatField(null=True)), migrations.AddField(model_name='rasterdataset', name='minimum_scale', field=models.FloatField(null=True)), migrations.AddField(model_name='vectordataset', name='maximum_scale', field=models.FloatField(null=True)), migrations.AddField(model_name='vectordataset', name='minimum_scale', field=models.FloatField(null=True))] class-attribute instance-attribute

0022_alter_customdataset_qgis_layer_id_and_more

Migration

Bases: Migration

Source code in src/georama/data_integration/migrations/0022_alter_customdataset_qgis_layer_id_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
class Migration(migrations.Migration):

    dependencies = [
        ('data_integration', '0021_customdataset_maximum_scale_and_more'),
    ]

    operations = [
        migrations.AlterField(
            model_name='customdataset',
            name='qgis_layer_id',
            field=models.CharField(max_length=1000, unique=True),
        ),
        migrations.AlterField(
            model_name='rasterdataset',
            name='qgis_layer_id',
            field=models.CharField(max_length=1000, unique=True),
        ),
        migrations.AlterField(
            model_name='vectordataset',
            name='qgis_layer_id',
            field=models.CharField(max_length=1000, unique=True),
        ),
    ]
dependencies = [('data_integration', '0021_customdataset_maximum_scale_and_more')] class-attribute instance-attribute
operations = [migrations.AlterField(model_name='customdataset', name='qgis_layer_id', field=models.CharField(max_length=1000, unique=True)), migrations.AlterField(model_name='rasterdataset', name='qgis_layer_id', field=models.CharField(max_length=1000, unique=True)), migrations.AlterField(model_name='vectordataset', name='qgis_layer_id', field=models.CharField(max_length=1000, unique=True))] class-attribute instance-attribute

0023_remove_customdataset_style_and_more

Migration

Bases: Migration

Source code in src/georama/data_integration/migrations/0023_remove_customdataset_style_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
class Migration(migrations.Migration):

    dependencies = [
        ("data_integration", "0022_alter_customdataset_qgis_layer_id_and_more"),
    ]

    operations = [
        migrations.RemoveField(
            model_name="customdataset",
            name="style",
        ),
        migrations.RemoveField(
            model_name="rasterdataset",
            name="style",
        ),
        migrations.RemoveField(
            model_name="vectordataset",
            name="style",
        ),
        migrations.AddField(
            model_name="customdataset",
            name="styles",
            field=models.JSONField(default=dict),
        ),
        migrations.AddField(
            model_name="rasterdataset",
            name="styles",
            field=models.JSONField(default=dict),
        ),
        migrations.AddField(
            model_name="vectordataset",
            name="styles",
            field=models.JSONField(default=dict),
        ),
    ]
dependencies = [('data_integration', '0022_alter_customdataset_qgis_layer_id_and_more')] class-attribute instance-attribute
operations = [migrations.RemoveField(model_name='customdataset', name='style'), migrations.RemoveField(model_name='rasterdataset', name='style'), migrations.RemoveField(model_name='vectordataset', name='style'), migrations.AddField(model_name='customdataset', name='styles', field=models.JSONField(default=dict)), migrations.AddField(model_name='rasterdataset', name='styles', field=models.JSONField(default=dict)), migrations.AddField(model_name='vectordataset', name='styles', field=models.JSONField(default=dict))] class-attribute instance-attribute

models

log = logging.getLogger(__name__) module-attribute

CustomDataSet

Bases: DataSet

Source code in src/georama/data_integration/models.py
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
class CustomDataSet(DataSet):
    class Meta:
        unique_together = (
            "name",
            "project",
        )

    project = models.ForeignKey(
        Project,
        related_name="custom_datasets",
        related_query_name="custom_dataset",
        on_delete=models.CASCADE,
    )

    @property
    def to_qsl(self) -> Custom:
        datasource, path = self.source_to_qsl
        return Custom(
            name=self.name,
            title=self.title,
            bbox=BBox.from_string(self.bbox),
            bbox_wgs84=BBox.from_string(self.bbox_wgs84),
            path=path,
            driver=self.driver,
            source=datasource,
            styles=DictDecoder().decode(self.styles, List[Style]),
            id=self.qgis_layer_id,
            crs=self.crs_to_qsl,
            minimum_scale=self.minimum_scale,
            maximum_scale=self.maximum_scale,
        )

project = models.ForeignKey(Project, related_name='custom_datasets', related_query_name='custom_dataset', on_delete=models.CASCADE) class-attribute instance-attribute

to_qsl property

Meta

Source code in src/georama/data_integration/models.py
169
170
171
172
173
class Meta:
    unique_together = (
        "name",
        "project",
    )
unique_together = ('name', 'project') class-attribute instance-attribute

DataSet

Bases: Model

Source code in src/georama/data_integration/models.py
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
class DataSet(models.Model):
    class Meta:
        abstract = True

    name = models.CharField(null=False, max_length=1000)
    qgis_layer_id = models.CharField(null=False, max_length=1000, unique=True)
    title = models.CharField(max_length=1000)
    bbox = models.CharField(max_length=1000)
    bbox_wgs84 = models.CharField(max_length=1000)
    path = models.CharField(max_length=10000)
    source = models.JSONField(default=dict)
    styles = models.JSONField(default=dict)
    # TODO: implement ENUM (wms, ogr, gdal, etc.)
    driver = models.CharField(max_length=50)
    # TODO: implement ENUM (raster, vector)
    crs = models.JSONField(default=dict)
    minimum_scale = models.FloatField(null=True)
    maximum_scale = models.FloatField(null=True)

    @property
    def source_to_qsl(self) -> tuple[DataSource, str]:
        # TODO: Implement an ENV Django app to manipulate datasources in a hookable way
        datasource = DictDecoder().decode(self.source, DataSource)
        path = self.path
        if datasource.postgres:
            datasource.postgres.host = "georama-test_data"
            datasource.postgres.port = "5432"
            path = path.replace("host=localhost", f"host={datasource.postgres.host}")
            path = path.replace("port=54322", f"port={datasource.postgres.port}")
            path = path.replace("host='localhost'", f"host={datasource.postgres.host}")
            path = path.replace("port='54322'", f"port={datasource.postgres.port}")
            print(path)
        elif datasource.ogr:
            path = os.path.join(self.project.mandant.name, path)
        elif datasource.gdal:
            path = os.path.join(self.project.mandant.name, path)

        return datasource, path

    @property
    def crs_to_qsl(self) -> Crs:
        config = ParserConfig(
            fail_on_unknown_attributes=False, fail_on_unknown_properties=False
        )
        return DictDecoder(config=config).decode(self.crs, Crs)

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

bbox = models.CharField(max_length=1000) class-attribute instance-attribute

bbox_wgs84 = models.CharField(max_length=1000) class-attribute instance-attribute

crs = models.JSONField(default=dict) class-attribute instance-attribute

crs_to_qsl property

driver = models.CharField(max_length=50) class-attribute instance-attribute

maximum_scale = models.FloatField(null=True) class-attribute instance-attribute

minimum_scale = models.FloatField(null=True) class-attribute instance-attribute

name = models.CharField(null=False, max_length=1000) class-attribute instance-attribute

path = models.CharField(max_length=10000) class-attribute instance-attribute

qgis_layer_id = models.CharField(null=False, max_length=1000, unique=True) class-attribute instance-attribute

source = models.JSONField(default=dict) class-attribute instance-attribute

source_to_qsl property

styles = models.JSONField(default=dict) class-attribute instance-attribute

title = models.CharField(max_length=1000) class-attribute instance-attribute

Meta

Source code in src/georama/data_integration/models.py
53
54
class Meta:
    abstract = True
abstract = True class-attribute instance-attribute

__str__()

Source code in src/georama/data_integration/models.py
98
99
def __str__(self):
    return f"{self.title} ({self.name})"

Field

Bases: Model

Source code in src/georama/data_integration/models.py
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
class Field(models.Model):
    class Meta:
        unique_together = (
            "name",
            "vector_dataset",
        )

    name = models.CharField(null=False, max_length=1000)
    type = models.CharField(null=False, max_length=1000)
    vector_dataset = models.ForeignKey(
        VectorDataSet,
        related_name="fields",
        related_query_name="field",
        on_delete=models.CASCADE,
    )

name = models.CharField(null=False, max_length=1000) class-attribute instance-attribute

type = models.CharField(null=False, max_length=1000) class-attribute instance-attribute

vector_dataset = models.ForeignKey(VectorDataSet, related_name='fields', related_query_name='field', on_delete=models.CASCADE) class-attribute instance-attribute

Meta

Source code in src/georama/data_integration/models.py
202
203
204
205
206
class Meta:
    unique_together = (
        "name",
        "vector_dataset",
    )
unique_together = ('name', 'vector_dataset') class-attribute instance-attribute

Mandant

Bases: Model

Source code in src/georama/data_integration/models.py
22
23
24
25
26
27
class Mandant(models.Model):
    name = models.CharField(unique=True)
    description = models.TextField(null=True)

    def __str__(self):
        return self.name

description = models.TextField(null=True) class-attribute instance-attribute

name = models.CharField(unique=True) class-attribute instance-attribute

__str__()

Source code in src/georama/data_integration/models.py
26
27
def __str__(self):
    return self.name

Project

Bases: Model

Source code in src/georama/data_integration/models.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Project(models.Model):
    name = models.CharField(null=False, max_length=1000)
    title = models.CharField(max_length=1000)
    version = models.CharField(max_length=1000)
    hash = models.CharField(max_length=20000, null=True, blank=True)
    integration_date = models.DateTimeField(default=datetime.datetime.now)
    mandant = models.ForeignKey(
        Mandant,
        related_name="mandants",
        related_query_name="mandant",
        on_delete=models.CASCADE,
        null=True,
    )

    class Meta:
        unique_together = (
            "name",
            "version",
            "mandant",
        )

hash = models.CharField(max_length=20000, null=True, blank=True) class-attribute instance-attribute

integration_date = models.DateTimeField(default=datetime.datetime.now) class-attribute instance-attribute

mandant = models.ForeignKey(Mandant, related_name='mandants', related_query_name='mandant', on_delete=models.CASCADE, null=True) class-attribute instance-attribute

name = models.CharField(null=False, max_length=1000) class-attribute instance-attribute

title = models.CharField(max_length=1000) class-attribute instance-attribute

version = models.CharField(max_length=1000) class-attribute instance-attribute

Meta

Source code in src/georama/data_integration/models.py
44
45
46
47
48
49
class Meta:
    unique_together = (
        "name",
        "version",
        "mandant",
    )
unique_together = ('name', 'version', 'mandant') class-attribute instance-attribute

RasterDataSet

Bases: DataSet

Source code in src/georama/data_integration/models.py
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
class RasterDataSet(DataSet):
    class Meta:
        unique_together = (
            "name",
            "project",
        )

    project = models.ForeignKey(
        Project,
        related_name="raster_datasets",
        related_query_name="raster_dataset",
        on_delete=models.CASCADE,
    )

    @property
    def to_qsl(self) -> Raster:
        datasource, path = self.source_to_qsl
        return Raster(
            name=self.name,
            title=self.title,
            bbox=BBox.from_string(self.bbox),
            bbox_wgs84=BBox.from_string(self.bbox_wgs84),
            path=path,
            driver=self.driver,
            source=datasource,
            styles=DictDecoder().decode(self.styles, List[Style]),
            id=self.qgis_layer_id,
            crs=self.crs_to_qsl,
            minimum_scale=self.minimum_scale,
            maximum_scale=self.maximum_scale,
        )

project = models.ForeignKey(Project, related_name='raster_datasets', related_query_name='raster_dataset', on_delete=models.CASCADE) class-attribute instance-attribute

to_qsl property

Meta

Source code in src/georama/data_integration/models.py
136
137
138
139
140
class Meta:
    unique_together = (
        "name",
        "project",
    )
unique_together = ('name', 'project') class-attribute instance-attribute

VectorDataSet

Bases: DataSet

Source code in src/georama/data_integration/models.py
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
class VectorDataSet(DataSet):
    class Meta:
        unique_together = (
            "name",
            "project",
        )

    project = models.ForeignKey(
        Project,
        related_name="vector_datasets",
        related_query_name="vector_dataset",
        on_delete=models.CASCADE,
    )

    @property
    def to_qsl(self) -> Vector:
        datasource, path = self.source_to_qsl
        return Vector(
            name=self.name,
            title=self.title,
            bbox=BBox.from_string(self.bbox),
            bbox_wgs84=BBox.from_string(self.bbox_wgs84),
            path=path,
            driver=self.driver,
            source=datasource,
            styles=DictDecoder().decode(self.styles, List[Style]),
            id=self.qgis_layer_id,
            crs=self.crs_to_qsl,
            minimum_scale=self.minimum_scale,
            maximum_scale=self.maximum_scale,
        )

project = models.ForeignKey(Project, related_name='vector_datasets', related_query_name='vector_dataset', on_delete=models.CASCADE) class-attribute instance-attribute

to_qsl property

Meta

Source code in src/georama/data_integration/models.py
103
104
105
106
107
class Meta:
    unique_together = (
        "name",
        "project",
    )
unique_together = ('name', 'project') class-attribute instance-attribute

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'))

app_name = 'georama.data_integration' module-attribute

urlpatterns = [path('register_qgis_project/<str:mandant_name>/<str:project_name>', views.RegisterQgisProject.as_view(), name='register_qgis_project')] module-attribute

views

log = logging.getLogger(__name__) module-attribute

RegisterQgisProject

Bases: View

Source code in src/georama/data_integration/views.py
 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
class RegisterQgisProject(View):
    def get_vector_dataset_by_id(self, id: str):
        vector_dataset_qs = VectorDataSet.objects.filter(qgis_layer_id=id)
        if vector_dataset_qs.exists():
            return vector_dataset_qs.get()
        else:
            return None

    @staticmethod
    def find_config_vector_dataset_field_by_name(vector_dataset: Vector, name: str):
        for field in vector_dataset.fields:
            if field.name == name:
                return field

    @staticmethod
    def find_config_vector_dataset_by_id(vector_datasets: list[Vector], id: str):
        for vector_dataset in vector_datasets:
            if vector_dataset.id == id:
                return vector_dataset

    @staticmethod
    def load_project_config(
        mandant_name: str, project_name: str
    ) -> Tuple[QgisProject, Config] | Tuple[None, None] | Tuple[QgisProject, None]:
        config = DataintgrationConfig()
        qpfs = QgisProjectFileStructure(config.path)
        qpfs.create_groups(config.qgis_project_extensions)
        group = qpfs.find_group_by_name(mandant_name)
        if not isinstance(group, QgisProjectGroup):
            return None, None
        project = group.find_project_by_name(project_name)
        if not isinstance(project, QgisProject):
            return None, None
        if not project.has_config:
            return project, None
        parser_config = ParserConfig(
            fail_on_unknown_properties=False, fail_on_unknown_attributes=False
        )
        parser = JsonParser(parser_config)
        project_config = parser.parse(project.config_path, Config)
        return project, project_config

    def get(self, request: HttpRequest, mandant_name: str, project_name: str, **kwargs):
        project, project_config = self.load_project_config(mandant_name, project_name)
        if not project_config or not project:
            redirect("admin:data_integration_project_changelist")
        mandant_qs = Mandant.objects.filter(name=mandant_name)
        if not mandant_qs.exists():
            mandant_db = Mandant(name=mandant_name)
            mandant_db.save()
        else:
            # we can do so, because name is unique in DB
            mandant_db = mandant_qs.get()
        project_qs = Project.objects.filter(name=project_name, mandant=mandant_db)
        if not project_qs.exists():
            log.error("Project does not exists, we first create a new DB object.")
            project_db = Project(
                mandant=mandant_db,
                name=project_name,
                hash=project.hash,
                title=project_config.project.name,
            )
            project_db.save()
        else:
            log.error("Project exists, we proceed with the DB object.")
            project_db = project_qs.get()
            if project_db.hash == project.hash:
                log.error("HASH of config and in DB was the same. No further work necessary.")
                return redirect("admin:data_integration_project_changelist")
        for layer in project_config.datasets.vector:
            vector_dataset = self.get_vector_dataset_by_id(layer.id)
            if vector_dataset is None:
                # there was no dataset with the corresponding qgis layer id, so we creare one
                vector_dataset = VectorDataSet(
                    project=project_db,
                    name=layer.name,
                    title=layer.title,
                    bbox=layer.bbox.to_string(),
                    bbox_wgs84=layer.bbox_wgs84.to_string(),
                    path=layer.path,
                    styles=DictEncoder().encode(layer.styles),
                    driver=layer.driver,
                    source=DictEncoder().encode(layer.source),
                    qgis_layer_id=layer.id,
                    crs=DictEncoder().encode(layer.crs),
                    minimum_scale=layer.minimum_scale,
                    maximum_scale=layer.maximum_scale,
                )
            else:
                # we found the dataset in the database and we update it
                vector_dataset.update(
                    project=project_db,
                    name=layer.name,
                    title=layer.title,
                    bbox=layer.bbox.to_string(),
                    bbox_wgs84=layer.bbox_wgs84.to_string(),
                    path=layer.path,
                    styles=DictEncoder().encode(layer.styles),
                    driver=layer.driver,
                    source=DictEncoder().encode(layer.source),
                    crs=DictEncoder().encode(layer.crs),
                    minimum_scale=layer.minimum_scale,
                    maximum_scale=layer.maximum_scale,
                )
            vector_dataset.save()
            for field in layer.fields:
                # loop through all fields in config
                field_qs = Field.objects.filter(
                    name=field.name, type=field.type, vector_dataset=vector_dataset
                )
                if not field_qs.exists():
                    # assure field does not exist in db
                    Field(
                        name=field.name, type=field.type, vector_dataset=vector_dataset
                    ).save()
            # finally get rid of old objects in the database which are not in the config anymore
            for field_db in Field.objects.filter(vector_dataset=vector_dataset).all():
                field_match = self.find_config_vector_dataset_field_by_name(
                    layer, field_db.name
                )
                if field_match is None:
                    # there is a fild in the db which does not exist in the config anymore
                    field_db.delete()
            for vector_dataset_db in VectorDataSet.objects.filter(project=project_db).all():
                vector_dataset_match = self.find_config_vector_dataset_by_id(
                    project_config.datasets.vector, vector_dataset_db.qgis_layer_id
                )
                if vector_dataset_match is None:
                    # there is a fild in the db which does not exist in the config anymore
                    vector_dataset_db.delete()
        for layer in project_config.datasets.raster:
            RasterDataSet(
                project=project_db,
                name=layer.name,
                title=layer.title,
                bbox=layer.bbox.to_string(),
                bbox_wgs84=layer.bbox_wgs84.to_string(),
                path=layer.path,
                styles=DictEncoder().encode(layer.styles),
                driver=layer.driver,
                source=DictEncoder().encode(layer.source),
                qgis_layer_id=layer.id,
                crs=DictEncoder().encode(layer.crs),
                minimum_scale=layer.minimum_scale,
                maximum_scale=layer.maximum_scale,
            ).save()
        for layer in project_config.datasets.custom:
            CustomDataSet(
                project=project_db,
                name=layer.name,
                title=layer.title,
                bbox=layer.bbox.to_string(),
                bbox_wgs84=layer.bbox_wgs84.to_string(),
                path=layer.path,
                styles=DictEncoder().encode(layer.styles),
                driver=layer.driver,
                source=DictEncoder().encode(layer.source),
                qgis_layer_id=layer.id,
                crs=DictEncoder().encode(layer.crs),
                minimum_scale=layer.minimum_scale,
                maximum_scale=layer.maximum_scale,
            ).save()
        return redirect("admin:data_integration_project_changelist")

find_config_vector_dataset_by_id(vector_datasets, id) staticmethod

Source code in src/georama/data_integration/views.py
46
47
48
49
50
@staticmethod
def find_config_vector_dataset_by_id(vector_datasets: list[Vector], id: str):
    for vector_dataset in vector_datasets:
        if vector_dataset.id == id:
            return vector_dataset

find_config_vector_dataset_field_by_name(vector_dataset, name) staticmethod

Source code in src/georama/data_integration/views.py
40
41
42
43
44
@staticmethod
def find_config_vector_dataset_field_by_name(vector_dataset: Vector, name: str):
    for field in vector_dataset.fields:
        if field.name == name:
            return field

get(request, mandant_name, project_name, **kwargs)

Source code in src/georama/data_integration/views.py
 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
def get(self, request: HttpRequest, mandant_name: str, project_name: str, **kwargs):
    project, project_config = self.load_project_config(mandant_name, project_name)
    if not project_config or not project:
        redirect("admin:data_integration_project_changelist")
    mandant_qs = Mandant.objects.filter(name=mandant_name)
    if not mandant_qs.exists():
        mandant_db = Mandant(name=mandant_name)
        mandant_db.save()
    else:
        # we can do so, because name is unique in DB
        mandant_db = mandant_qs.get()
    project_qs = Project.objects.filter(name=project_name, mandant=mandant_db)
    if not project_qs.exists():
        log.error("Project does not exists, we first create a new DB object.")
        project_db = Project(
            mandant=mandant_db,
            name=project_name,
            hash=project.hash,
            title=project_config.project.name,
        )
        project_db.save()
    else:
        log.error("Project exists, we proceed with the DB object.")
        project_db = project_qs.get()
        if project_db.hash == project.hash:
            log.error("HASH of config and in DB was the same. No further work necessary.")
            return redirect("admin:data_integration_project_changelist")
    for layer in project_config.datasets.vector:
        vector_dataset = self.get_vector_dataset_by_id(layer.id)
        if vector_dataset is None:
            # there was no dataset with the corresponding qgis layer id, so we creare one
            vector_dataset = VectorDataSet(
                project=project_db,
                name=layer.name,
                title=layer.title,
                bbox=layer.bbox.to_string(),
                bbox_wgs84=layer.bbox_wgs84.to_string(),
                path=layer.path,
                styles=DictEncoder().encode(layer.styles),
                driver=layer.driver,
                source=DictEncoder().encode(layer.source),
                qgis_layer_id=layer.id,
                crs=DictEncoder().encode(layer.crs),
                minimum_scale=layer.minimum_scale,
                maximum_scale=layer.maximum_scale,
            )
        else:
            # we found the dataset in the database and we update it
            vector_dataset.update(
                project=project_db,
                name=layer.name,
                title=layer.title,
                bbox=layer.bbox.to_string(),
                bbox_wgs84=layer.bbox_wgs84.to_string(),
                path=layer.path,
                styles=DictEncoder().encode(layer.styles),
                driver=layer.driver,
                source=DictEncoder().encode(layer.source),
                crs=DictEncoder().encode(layer.crs),
                minimum_scale=layer.minimum_scale,
                maximum_scale=layer.maximum_scale,
            )
        vector_dataset.save()
        for field in layer.fields:
            # loop through all fields in config
            field_qs = Field.objects.filter(
                name=field.name, type=field.type, vector_dataset=vector_dataset
            )
            if not field_qs.exists():
                # assure field does not exist in db
                Field(
                    name=field.name, type=field.type, vector_dataset=vector_dataset
                ).save()
        # finally get rid of old objects in the database which are not in the config anymore
        for field_db in Field.objects.filter(vector_dataset=vector_dataset).all():
            field_match = self.find_config_vector_dataset_field_by_name(
                layer, field_db.name
            )
            if field_match is None:
                # there is a fild in the db which does not exist in the config anymore
                field_db.delete()
        for vector_dataset_db in VectorDataSet.objects.filter(project=project_db).all():
            vector_dataset_match = self.find_config_vector_dataset_by_id(
                project_config.datasets.vector, vector_dataset_db.qgis_layer_id
            )
            if vector_dataset_match is None:
                # there is a fild in the db which does not exist in the config anymore
                vector_dataset_db.delete()
    for layer in project_config.datasets.raster:
        RasterDataSet(
            project=project_db,
            name=layer.name,
            title=layer.title,
            bbox=layer.bbox.to_string(),
            bbox_wgs84=layer.bbox_wgs84.to_string(),
            path=layer.path,
            styles=DictEncoder().encode(layer.styles),
            driver=layer.driver,
            source=DictEncoder().encode(layer.source),
            qgis_layer_id=layer.id,
            crs=DictEncoder().encode(layer.crs),
            minimum_scale=layer.minimum_scale,
            maximum_scale=layer.maximum_scale,
        ).save()
    for layer in project_config.datasets.custom:
        CustomDataSet(
            project=project_db,
            name=layer.name,
            title=layer.title,
            bbox=layer.bbox.to_string(),
            bbox_wgs84=layer.bbox_wgs84.to_string(),
            path=layer.path,
            styles=DictEncoder().encode(layer.styles),
            driver=layer.driver,
            source=DictEncoder().encode(layer.source),
            qgis_layer_id=layer.id,
            crs=DictEncoder().encode(layer.crs),
            minimum_scale=layer.minimum_scale,
            maximum_scale=layer.maximum_scale,
        ).save()
    return redirect("admin:data_integration_project_changelist")

get_vector_dataset_by_id(id)

Source code in src/georama/data_integration/views.py
33
34
35
36
37
38
def get_vector_dataset_by_id(self, id: str):
    vector_dataset_qs = VectorDataSet.objects.filter(qgis_layer_id=id)
    if vector_dataset_qs.exists():
        return vector_dataset_qs.get()
    else:
        return None

load_project_config(mandant_name, project_name) staticmethod

Source code in src/georama/data_integration/views.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
@staticmethod
def load_project_config(
    mandant_name: str, project_name: str
) -> Tuple[QgisProject, Config] | Tuple[None, None] | Tuple[QgisProject, None]:
    config = DataintgrationConfig()
    qpfs = QgisProjectFileStructure(config.path)
    qpfs.create_groups(config.qgis_project_extensions)
    group = qpfs.find_group_by_name(mandant_name)
    if not isinstance(group, QgisProjectGroup):
        return None, None
    project = group.find_project_by_name(project_name)
    if not isinstance(project, QgisProject):
        return None, None
    if not project.has_config:
        return project, None
    parser_config = ParserConfig(
        fail_on_unknown_properties=False, fail_on_unknown_attributes=False
    )
    parser = JsonParser(parser_config)
    project_config = parser.parse(project.config_path, Config)
    return project, project_config