diff options
author | Thomas André <thomas.andre@iggdrasil.net> | 2025-05-02 18:13:45 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2025-07-29 08:49:03 +0200 |
commit | 0c247e34e79978ba910c01c56528718cbce4e2d5 (patch) | |
tree | ce9fd077037d72b815afdda1cdf5524c7fdd50a7 /ishtar_common/views_item.py | |
parent | 63a6b5021626e956e6151ba3cc1e358aabf29e8a (diff) | |
download | Ishtar-0c247e34e79978ba910c01c56528718cbce4e2d5.tar.bz2 Ishtar-0c247e34e79978ba910c01c56528718cbce4e2d5.zip |
QField project export done and tested + saving some of the specifics importer for QField
Diffstat (limited to 'ishtar_common/views_item.py')
-rw-r--r-- | ishtar_common/views_item.py | 152 |
1 files changed, 114 insertions, 38 deletions
diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index 4126219fd..bd8780ea9 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -32,6 +32,7 @@ import subprocess # nosec from tempfile import NamedTemporaryFile from osgeo import ogr, osr import shutil +from zipfile import ZipFile from django.apps import apps from django.conf import settings @@ -2374,7 +2375,7 @@ def get_item( EMPTY = "[]" if not return_query and data_type not in ( - "json", "csv", "json-image", "json-map", "json-stats"): + "json", "csv", "json-image", "json-map", "json-stats", "gpkg"): return HttpResponse(EMPTY, content_type="text/plain") if data_type == "json-stats" and len(model.STATISTIC_MODALITIES) < 2: @@ -2991,7 +2992,7 @@ def get_item( items, query_table_cols, my_extra_request_keys, geo_fields=geo_fields ) - elif data_type != "csv" and getattr(model, "NEW_QUERY_ENGINE", False): + elif data_type not in ["csv", "gpkg"] and getattr(model, "NEW_QUERY_ENGINE", False): datas = _get_data_from_query(items, query_table_cols, my_extra_request_keys) else: datas = _get_data_from_query_old( @@ -3218,22 +3219,40 @@ def get_item( except UnicodeEncodeError: vals.append(unidecode(v).encode(ENCODING).decode(ENCODING)) writer.writerow(vals) - #return response + return response elif data_type == "gpkg": # Work in progress - # Creation of the .gpkg + # I. Preparations driver = ogr.GetDriverByName("GPKG") - root = settings.LIB_BASE_PATH + "ishtar_common/tests/" - filename = os.path.join(root, "Finds.gpkg") + root = settings.LIB_BASE_PATH + "ishtar_common/qfield/" + # 1) Creation of the .gpkg + filename = os.path.join(root, "export", "Finds.gpkg") # Verification to delete it if already existing if os.path.exists(filename): os.remove(filename) datasource = driver.CreateDataSource(filename) srs = osr.SpatialReference() srs.ImportFromEPSG(4326) - # Layer creation - layer = datasource.CreateLayer("Finds", srs, ogr.wkbPoint) - # Getting all the column names (copy from below) + # 2) Preparations for the modification of the style in the .qgs file + qgs_path = os.path.join(root, "model", "Prospections.qgs") + new_qgs = os.path.join(root, "export", "Prospections.qgs") + if os.path.exists(new_qgs): + os.remove(new_qgs) + # 3) Duplication of the .zip for export + project = os.path.join(root, "model", "Prospections_qfield.zip") + duplicate = os.path.join(root, "export", "Prospections_qfield_export.zip") + if os.path.exists(duplicate): + os.remove(duplicate) + shutil.copyfile(project, duplicate) + # II. Populating of the .gpkg + # 1) Layer creation with verification of the type of geometry to create + if "base_finds__point_2d" in table_cols: + layer = datasource.CreateLayer("Finds", srs, ogr.wkbPoint) + elif any(elem in table_cols for elem in ["base_finds__point_3d", "_z"]): + layer = datasource.CreateLayer("Finds", srs, ogr.wkbPoint25D) + else: + layer = datasource.CreateLayer("Finds", srs, ogr.wkbPolygon) + # 2) Getting all the column names (copy from below) if col_names: col_names = [name for name in col_names] else: @@ -3258,44 +3277,101 @@ def get_item( ) continue col_names.append(str(field.verbose_name)) - # Creation of the columns - for name in col_names: - layer.CreateField(ogr.FieldDefn(name, ogr.OFTString)) + # 3) Creation of the attributes + print("II.3)") + for idx in range(0, len(col_names)): + if any(elem in table_cols[idx] for elem in ["index", "order", "quantity", "taq", "tpq", "year"]): + layer.CreateField(ogr.FieldDefn(col_names[idx], ogr.OFTInteger64)) + elif any(elem in table_cols[idx] for elem in ["_x", "_y", "_z", "circumference", "cost", "depth", "diameter", "height", "length", "number", "surface", "side", "thickness", "value", "volume", "weight", "width"]): + layer.CreateField(ogr.FieldDefn(col_names[idx], ogr.OFTReal)) + elif "_date" in table_cols[idx]: + layer.CreateField(ogr.FieldDefn(col_names[idx], ogr.OFTDate)) + elif "_datetime" in table_cols[idx]: + layer.CreateField(ogr.FieldDefn(col_names[idx], ogr.OFTDateTime)) + elif any(elem in table_cols[idx] for elem in ["large_area_prescription", "is_complete", "executed"]): + layer.CreateField(ogr.FieldDefn(col_names[idx], ogr.OFTBinary)) + else: + layer.CreateField(ogr.FieldDefn(col_names[idx], ogr.OFTString)) + idx += 1 max = len(col_names) - # Looping on all the datas extracted + # Looping on all the datas extracted to create features for data in datas: # Creation of a new feature feature = ogr.Feature(layer.GetLayerDefn()) + # Preparations for the geometry + point = "" + geom_x = "" + geom_y = "" + geom_z = "" # Looping on the attributes to add them to the feature - for n in range (0, max) : - # +1 because the first value in the attributes is '' - m = n + 1 - feature.SetField(col_names[n], str(data[m])) - # First version to create the geometry of the feature - # Work in progress - if "x" in col_names[n] or "X" in col_names[n]: - try: - float(data[m]) - geom_x = data[m] - except: - pass - if "y" in col_names[n] or "Y" in col_names[n]: + for idx in range (0, max) : + # 4) Completion of the attributes + if any(elem == table_cols[idx] for elem in ["_date", "_datetime"]): + # Preparations for specific values for the date and date_time try: - float(data[m]) - geom_y = data[m] + # First version if it has all the data necessary for an ogr.OFTDateTime + # +1 because the first value in the attributes is '' + feature.SetField(col_names[idx], data[idx + 1]) except: - pass - try: - point = ogr.Geometry(ogr.wkbPoint) - point.AddPoint(float(geom_x), float(geom_y)) - feature.SetGeometry(point) - layer.CreateFeature(feature) - except: - pass + # Second version if some values are missing + # +1 because the first value in the attributes is '' + feature.SetField(col_names[idx], data[idx + 1].year, data[idx + 1].month, data[idx + 1].day, 0, 0, 0) + else: + # +1 because the first value in the attributes is '' + feature.SetField(col_names[idx], str(data[idx + 1])) + # 5) Gestion of the geometry + if any(elem in table_cols for elem in ["base_finds__point_2d", "base_finds__point_3d", "_line", "_points", "_polygon"]): + if table_cols[idx] in ["base_finds__point_2d", "base_finds__point_3d", "_line", "_points", "_polygon"]: + try: + point = ogr.CreateGeometryFromWkt(data[idx + 1].split(";")[1]) + except: + pass + else: + if "base_finds__x" and "base_finds__y" in table_cols: + if table_cols[idx] == "base_finds__x": + geom_x = data[idx + 1] + elif table_cols[idx] == "base_finds__y": + geom_y = data[idx + 1] + if "base_finds__z" in table_cols: + if table_cols[idx] == "base_finds__z": + geom_z = data[idx + 1] + # Prevent problems when both x,y and geometry are present + if point == "" and geom_x != "" and geom_y != "": + if geom_z != "": + point = ogr.Geometry(ogr.wkbPoint25D) + point.AddPoint(float(geom_x), float(geom_y), float(geom_z)) + else: + point = ogr.Geometry(ogr.wkbPoint) + point.AddPoint(float(geom_x), float(geom_y)) + if point != "": + feature.SetGeometry(point) + layer.CreateFeature(feature) feature = None datasource = None - # Missing : Part where the new .gpkg is moved to a copy of the QField folder - # Work in progress + # 6) Modification of the style + list_ref = ["champ_id", "champ_date", "champ_datetime", "champ_x", "champ_y", "champ_z", "champ_media", "champ_wkt_2d", "champ_wkt_3d"] + list_search = ["label", "_date", "_datetime", "base_finds__x", "base_finds__y", "base_finds__z", "_image", "__point_2d", "__point_2d"] + text = open(qgs_path, encoding='utf-8').read() + for elem in list_search: + for col in table_cols: + if elem in col: + id_old = list_search.index(elem) + id_new = table_cols.index(col) + text = text.replace(list_ref[id_old], col_names[id_new]) + else: + pass + with open(new_qgs, 'w', encoding='utf-8') as file: + file.write(text) + # III. Moving the .gpkg in a copy of the Qfield test project + with ZipFile(duplicate, 'a') as zip_file: + # Adding the .gpkg to the .zip + zip_file.write(filename, os.path.basename(filename)) + zip_file.write(new_qgs, os.path.basename(new_qgs)) + # Closing of the .zip + zip_file.close() + response = HttpResponse(open(duplicate, 'rb'), content_type='application/zip') + response['Content-Disposition'] = 'attachment; filename="Qfield_prospections.zip"' + return response return HttpResponse("{}", content_type="text/plain") return func |