python - AdminModelConvertor for Geometry Field (LON/LAT) -
i want create view flask-admin enter coordinates in geometry field. how can create 2 textfields , convert them geometry object?
this have tried far (besides uncountable other things)
class customadminconverter(adminmodelconverter): @converts('geoalchemy2.types.geometry') def convert_geometry(self, field_args, **extra): return waytocoordinatesfield(**field_args) class waytocoordinatesfield(wtf.textareafield): def process_data(self, value): print "run" #is never called?? if value none: value = {} else: value = "test" return value class poiview(modelview): inline_model_form_converter = myinlinemodelconverter model_form_converter=customadminconverter can_create = true def __init__(self, session, **kwargs): # can pass name , other parameters if want super(poiview, self).__init__(poi, session, **kwargs) def scaffold_form(self): form_class = super(poiview, self).scaffold_form() form_class.way = wtf.textareafield("coordinates") return form_class
the poi object looks this:
class poi(db.model): __tablename__ = 'zo_poi' id = db.column(db.integer, primary_key=true) name = db.column(db.text()) tags = db.column(hstore()) src = db.column(db.text()) way = db.column(geometry('point')) intern = db.column(db.boolean())
thanks lot help!
got solution interactive map. here have done:
admin/fields.py:
import json wtforms import field import geojson shapely.geometry import asshape geoalchemy2.shape import to_shape, from_shape wtforms.widgets import html_params, htmlstring geoalchemy2.elements import wktelement, wkbelement flask import render_template class wtformsmapinput(object): def __call__(self, field, **kwargs): options = dict(name=field.name, value=field.data, height=field.height, width=field.width, geometry_type=field.geometry_type) return htmlstring(render_template("admin/admin_map.html", height=options['height'], width=options['width'], geolayer=self.geolayer(field.data), preview=false)) def geolayer(self, value): if value not none: html = "" subme = """var geojson = json.parse('%s'); editablelayers.adddata(geojson); update() map.fitbounds(editablelayers.getbounds());""" # if validation in flask-admin fails on somethign other # spatial column, never converted geojson. didn't # spend time figure out why, convert here. if isinstance(value, (wktelement, wkbelement)): html += subme % geojson.dumps(to_shape(value)) else: html += subme % geojson.dumps(value) return html class wtformsmapfield(field): widget = wtformsmapinput() def __init__(self, label='', validators=none, geometry_type=none, width=500, height=500, **kwargs): super(wtformsmapfield, self).__init__(label, validators, **kwargs) self.width = width self.height = height self.geometry_type = geometry_type def _value(self): """ called widget geojson representation of object """ if self.data: return self.data else: return json.loads(json.dumps(dict())) def process_formdata(self, valuelist): """ convert geojson db object """ if valuelist: geo_ob = geojson.loads(valuelist[0]) self.data = from_shape(asshape(geo_ob.geometry)) else: self.data = none def process_data(self, value): """ convert db object geojson """ if value not none: self.data = geojson.loads(geojson.dumps(to_shape(value))) print self.data else: self.data = none
templates/admin/admin_map.html
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css"/> <link rel="stylesheet" href="http://leaflet.github.io/leaflet.draw/leaflet.draw.css"/> <script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script> <script src="http://leaflet.github.io/leaflet.draw/leaflet.draw.js"></script> <script src="/admin/static/vendor/jquery-1.8.3.min.js" type="text/javascript"></script> <script src="/static/js/googleoverlay/layer/tile/google.js"></script> <script src="http://maps.google.com/maps/api/js?v=3&sensor=false"></script> <div id="map" style="height: {{ height }}px; width: {{ width }}px;"></div> <input id="geojson" type="text" name="{{ name }}"/> <script> var map = new l.map('map', { center: new l.latlng(47.3682, 8.879), zoom: 11 {% if preview %} , dragging: false, touchzoom: false, scrollwheelzoom: false, doubleclickzoom: false, boxzoom: false, tap: false, keyboard: false, zoomcontrol: false {% endif %} } ); var ggl = new l.google('roadmap'); map.addlayer(ggl); var osm = new l.tilelayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'); map.addcontrol(new l.control.layers({'openstreetmap': osm, 'google maps': ggl}, {})); var editablelayers = l.geojson().addto(map); {{ geolayer |safe }} {% if not preview %} var drawcontrol = new l.control.draw({ position: 'topright', draw: { polyline: false, circle: false, rectangle: false, polygon: true, marker: true, }, edit: { featuregroup: editablelayers } }); {% endif %} map.addcontrol(drawcontrol); map.on('draw:created', function (e) { editablelayers.addlayer(e.layer); update(); }); map.on('draw:edited', function (e) { // use first layer update(); }) map.on('draw:deleted', function (e) { update(); }) function update() { if (editablelayers.getlayers().length > 0) { $("#geojson").val(json.stringify(editablelayers.getlayers()[0].togeojson())); } else { $("#geojson").val(null); } } </script>
admin/views.py
class poiview(modelview): can_create = true form_overrides = dict(location=wtformsmapfield) form_args = dict( way=dict( geometry_type='polygon', height=500, width=500 ) ) column_formatters = dict(tags=lambda v, c, m, p: (u', '.join(u"=".join([k, v]) k, v in m.tags.items())), ) def __init__(self, session, **kwargs): super(poiview, self).__init__(poi, session, **kwargs) def scaffold_form(self): form_class = super(poiview, self).scaffold_form() form_class.way = wtformsmapfield() form_class.tags = myselect2tagsfield("tags",none) return form_class
admin/models.py
class poi(db.model): __tablename__ = 'zo_poi' id = db.column(db.integer, primary_key=true) name = db.column(db.text()) tags = db.column(hstore()) src = db.column(db.text()) way = db.column(geometry('point', srid=4326)) intern = db.column(db.boolean())
Comments
Post a Comment