def editFeature(request, shapefile_id, feature_id=None): """ Let the user add or edit a feature within the given shapefile. 'feature_id' will be None if we are adding a new feature. """ shapefile = Shapefile.objects.get(id=shapefile_id) if request.method == "POST" and "delete" in request.POST: # User clicked on the "Delete" button -> show "Delete Feature" page. return HttpResponseRedirect("/shape-editor/deleteFeature/" + shapefile_id + "/" + feature_id) geometryField = utils.calcGeometryField(shapefile.geom_type) formType = shapefileEditor.getMapForm(shapefile) if feature_id == None: # Adding a new feature. feature = Feature(shapefile=shapefile) attributes = [] else: # Editing an existing feature. feature = Feature.objects.get(id=feature_id) # Get the attributes for this feature. attributes = [] # List of (name, value) tuples. for attrValue in feature.attributevalue_set.all(): attributes.append([attrValue.attribute.name, attrValue.value]) attributes.sort() # Display the form. if request.method == "GET": wkt = getattr(feature, geometryField) form = formType({'geometry' : wkt}) return render_to_response("editFeature.html", {'shapefile' : shapefile, 'form' : form, 'attributes' : attributes}) elif request.method == "POST": form = formType(request.POST) try: if form.is_valid(): wkt = form.cleaned_data['geometry'] setattr(feature, geometryField, wkt) feature.save() # Return the user to the "select feature" page. return HttpResponseRedirect("/shape-editor/edit/" + shapefile_id) except ValueError: pass return render_to_response("editFeature.html", {'shapefile' : shapefile, 'form' : form, 'attributes' : attributes})
def importData(shapefile, characterEncoding): """ Attempt to import the contents of a shapefile into our database. 'shapefile' is the Django UploadedFile object that was uploaded, and 'characterEncoding' is the character encoding to use for interpreting the shapefile's string attributes. We return None if the import succeeded. Otherwise we return a string containing a suitable error message explaining why the shapefile can't be imported. """ # Copy the zip archive into a temporary file. fd,fname = tempfile.mkstemp(suffix=".zip") os.close(fd) f = open(fname, "wb") for chunk in shapefile.chunks(): f.write(chunk) f.close() # Open the zip file and check its contents. if not zipfile.is_zipfile(fname): os.remove(fname) return "Not a valid zip archive." zip = zipfile.ZipFile(fname) required_suffixes = [".shp", ".shx", ".dbf", ".prj"] hasSuffix = {} for suffix in required_suffixes: hasSuffix[suffix] = False for info in zip.infolist(): extension = os.path.splitext(info.filename)[1].lower() if extension in required_suffixes: hasSuffix[extension] = True else: print "Extraneous file: " + info.filename for suffix in required_suffixes: if not hasSuffix[suffix]: zip.close() os.remove(fname) return "Archive missing required " + suffix + " file." # Decompress the zip archive into a temporary directory. At the same # time, we get the name of the main ".shp" file. zip = zipfile.ZipFile(fname) shapefileName = None dirname = tempfile.mkdtemp() for info in zip.infolist(): if info.filename.endswith(".shp"): shapefileName = info.filename dstFile = os.path.join(dirname, info.filename) f = open(dstFile, "wb") f.write(zip.read(info.filename)) f.close() zip.close() # Attempt to open the shapefile. try: datasource = ogr.Open(os.path.join(dirname, shapefileName)) layer = datasource.GetLayer(0) shapefileOK = True except: traceback.print_exc() shapefileOK = False if not shapefileOK: os.remove(fname) shutil.rmtree(dirname) return "Not a valid shapefile." # Import the data from the opened shapefile. geometryType = layer.GetLayerDefn().GetGeomType() geometryName = utils.ogrTypeToGeometryName(geometryType) srcSpatialRef = layer.GetSpatialRef() dstSpatialRef = osr.SpatialReference() dstSpatialRef.ImportFromEPSG(4326) shapefile = Shapefile(filename=shapefileName, srs_wkt=srcSpatialRef.ExportToWkt(), geom_type=geometryName, encoding=characterEncoding) shapefile.save() attributes = [] layerDef = layer.GetLayerDefn() for i in range(layerDef.GetFieldCount()): fieldDef = layerDef.GetFieldDefn(i) attr = Attribute(shapefile=shapefile, name=fieldDef.GetName(), type=fieldDef.GetType(), width=fieldDef.GetWidth(), precision=fieldDef.GetPrecision()) attr.save() attributes.append(attr) coordTransform = osr.CoordinateTransformation(srcSpatialRef, dstSpatialRef) for i in range(layer.GetFeatureCount()): srcFeature = layer.GetFeature(i) srcGeometry = srcFeature.GetGeometryRef() srcGeometry.Transform(coordTransform) geometry = GEOSGeometry(srcGeometry.ExportToWkt()) geometry = utils.wrapGEOSGeometry(geometry) geometryField = utils.calcGeometryField(geometryName) args = {} args['shapefile'] = shapefile args[geometryField] = geometry feature = Feature(**args) feature.save() for attr in attributes: success,result = \ utils.getOGRFeatureAttribute(attr, srcFeature, characterEncoding) if not success: os.remove(fname) shutil.rmtree(dirname) shapefile.delete() return result attrValue = AttributeValue(feature=feature, attribute=attr, value=result) attrValue.save() # Finally, clean everything up. os.remove(fname) shutil.rmtree(dirname) return None # success.