예제 #1
0
파일: views.py 프로젝트: kakaTyx/geoedit
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})
예제 #2
0
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.