I'd recommend following technology stack: a PostGIS database in combination with a python backend (I recommend flask - http://flask.pocoo.org/) serving JSON, which then gets displayed in the frontend on a map powered by leaflet (http://leafletjs.com/) and some sprinkles of javascript to render the attribute table; a framework like backbone or angularjs would be overkill.
Here is a sample for the python backend (be aware that this is just a quick and messy example which should never be run in production!). It queries against the geonames dataset and returns id and name as attribute to display in a table as well as a geojson to display in a map. The query-url would be:
host/search?lat=48&lon=12&rad=1
with the radius rad in degrees.
from flask import Flask, jsonify, url_for, request
import psycopg2
import json
conn = psycopg2.connect(database='***', user='***')
curs = conn.cursor()
app = Flask(__name__)
@app.route("/search")
def search():
# GET data from request
data = (request.args.get('lat', ''), request.args.get('lon', ''), request.args.get('rad', ''))
# Query PostGIS
curs.execute("""\
SELECT geonameid, name, ST_Distance(geom, point) as distance, ST_AsGeoJSON(geom)
FROM geotest, (SELECT ST_MakePoint(%s, %s) AS point) AS f
WHERE ST_DWithin(geom, point, %s)
ORDER BY ST_Distance(geom, point) ASC;""", data)
res = []
# build response
for row in curs.fetchall():
rec = {"id": row[0], "name": row[1], "distance": row[2], "geojson": json.loads(row[3])}
res.append(rec)
# serve response
resp_data = json.dumps(res)
return Response(resp_data, status=200, mimetype='application/json')
if __name__ == "__main__":
app.debug = True
app.run()