Ответ Дика Фейнмана - это работоспособное решение для любых обстоятельств, в которых JQuery не подходит или не требуется иным образом.Как отмечает ComFreek, для этого необходимо установить заголовки CORS на стороне сервера.Если это ваша служба, и вы справляетесь с более широким вопросом безопасности, то это вполне осуществимо.
Вот список службы Flask, настройка заголовков CORS, получение данных из базы данных, ответ JSONи успешно работает с подходом ДикФейнмана на стороне клиента:
#!/usr/bin/env python
from __future__ import unicode_literals
from flask import Flask, Response, jsonify, redirect, request, url_for
from your_model import *
import os
try:
import simplejson as json;
except ImportError:
import json
try:
from flask.ext.cors import *
except:
from flask_cors import *
app = Flask(__name__)
@app.before_request
def before_request():
try:
# Provided by an object in your_model
app.session = SessionManager.connect()
except:
print "Database connection failed."
@app.teardown_request
def shutdown_session(exception=None):
app.session.close()
# A route with a CORS header, to enable your javascript client to access
# JSON created from a database query.
@app.route('/whatever-data/', methods=['GET', 'OPTIONS'])
@cross_origin(headers=['Content-Type'])
def json_data():
whatever_list = []
results_json = None
try:
# Use SQL Alchemy to select all Whatevers, WHERE size > 0.
whatevers = app.session.query(Whatever).filter(Whatever.size > 0).all()
if whatevers and len(whatevers) > 0:
for whatever in whatevers:
# Each whatever is able to return a serialized version of itself.
# Refer to your_model.
whatever_list.append(whatever.serialize())
# Convert a list to JSON.
results_json = json.dumps(whatever_list)
except SQLAlchemyError as e:
print 'Error {0}'.format(e)
exit(0)
if len(whatevers) < 1 or not results_json:
exit(0)
else:
# Because we used json.dumps(), rather than jsonify(),
# we need to create a Flask Response object, here.
return Response(response=str(results_json), mimetype='application/json')
if __name__ == '__main__':
#@NOTE Not suitable for production. As configured,
# your Flask service is in debug mode and publicly accessible.
app.run(debug=True, host='0.0.0.0', port=5001) # http://localhost:5001/
your_model содержит метод сериализации для всего, что угодно, а также менеджер соединений с базой данных (который может выдержать небольшой рефакторинг, но достаточно для централизации)создание сеансов базы данных в больших системах или архитектурах модель / представление / управление).Это происходит с использованием PostgreSQL, но с таким же успехом можно использовать любое хранилище данных на стороне сервера:
#!/usr/bin/env python
# Filename: your_model.py
import time
import psycopg2
import psycopg2.pool
import psycopg2.extras
from psycopg2.extensions import adapt, register_adapter, AsIs
from sqlalchemy import update
from sqlalchemy.orm import *
from sqlalchemy.exc import *
from sqlalchemy.dialects import postgresql
from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
class SessionManager(object):
@staticmethod
def connect():
engine = create_engine('postgresql://id:passwd@localhost/mydatabase',
echo = True)
Session = sessionmaker(bind = engine,
autoflush = True,
expire_on_commit = False,
autocommit = False)
session = Session()
return session
@staticmethod
def declareBase():
engine = create_engine('postgresql://id:passwd@localhost/mydatabase', echo=True)
whatever_metadata = MetaData(engine, schema ='public')
Base = declarative_base(metadata=whatever_metadata)
return Base
Base = SessionManager.declareBase()
class Whatever(Base):
"""Create, supply information about, and manage the state of one or more whatever.
"""
__tablename__ = 'whatever'
id = Column(Integer, primary_key=True)
whatever_digest = Column(VARCHAR, unique=True)
best_name = Column(VARCHAR, nullable = True)
whatever_timestamp = Column(BigInteger, default = time.time())
whatever_raw = Column(Numeric(precision = 1000, scale = 0), default = 0.0)
whatever_label = Column(postgresql.VARCHAR, nullable = True)
size = Column(BigInteger, default = 0)
def __init__(self,
whatever_digest = '',
best_name = '',
whatever_timestamp = 0,
whatever_raw = 0,
whatever_label = '',
size = 0):
self.whatever_digest = whatever_digest
self.best_name = best_name
self.whatever_timestamp = whatever_timestamp
self.whatever_raw = whatever_raw
self.whatever_label = whatever_label
# Serialize one way or another, just handle appropriately in the client.
def serialize(self):
return {
'best_name' :self.best_name,
'whatever_label':self.whatever_label,
'size' :self.size,
}
В ретроспективе я мог бы сериализовать любые объекты в виде списков, а не Python, который мог бы упроститьих обработка в службе Flask, и я мог бы лучше разделить проблемы в реализации Flask (вызов базы данных, вероятно, не должен быть встроен в обработчик маршрута), но вы можете улучшить это, как толькоу вас есть рабочее решение в вашей собственной среде разработки.
Кроме того, я не предлагаю людям избегать JQuery.Но если JQuery по той или иной причине отсутствует, этот подход кажется разумной альтернативой.
В любом случае это работает.
Вот моя реализация подхода Дика Фейнмана в клиенте:
<script type="text/javascript">
var addr = "dev.yourserver.yourorg.tld"
var port = "5001"
function Get(whateverUrl){
var Httpreq = new XMLHttpRequest(); // a new request
Httpreq.open("GET",whateverUrl,false);
Httpreq.send(null);
return Httpreq.responseText;
}
var whatever_list_obj = JSON.parse(Get("http://" + addr + ":" + port + "/whatever-data/"));
whatever_qty = whatever_list_obj.length;
for (var i = 0; i < whatever_qty; i++) {
console.log(whatever_list_obj[i].best_name);
}
</script>
Я не собираюсь перечислять вывод своей консоли, но я смотрю на длинный список строк what.best_name.
Еще к делу: what_list_obj доступен для использования в моем пространстве имен javascript, для независимо от , что я хочу сделать с ним, ... что может включать генерацию графики с D3.js,отображение с OpenLayers или CesiumJS, или вычисление некоторых промежуточных значений, которые не имеют особой необходимости жить в моем DOM.