2017-03-10 2 views
0

Ich habe ein Jquery-Skript, das eine Ajax-Post-Anfrage an eine Route auf meinem Flaschen-Server sendet. Ich möchte die Route eine SQLAlchemy Select-Abfrage berechnen und das Ergebnis an die jquery-Skript zurückgeben.flask-sqlalchemy query durch ajax jquery: json antwort?

Das Problem ist, dass ich nicht finden kann, eine einfache und generische Möglichkeit, die sqlalchemy Abfrage Ergebnis direkt in JSON, oder ein anderes Format von Javascript zu konvertieren.

Also für den Moment muss ich eine lange dedicated "serialize()" -Funktion für alle meine Klassen programmieren, um str() die gefährlichen Typen wie datetime zu werfen und dann jsonify.

Aber ich möchte nur eine Funktion haben, um direkt in einer Zeile die Ergebnisse der SQL-Anfrage zu konvertieren, nicht eine spezialisierte Funktion für jede SQL-Klasse. Hier

ist ein Beispiel dafür, was ich jetzt tue:

Die Route in ANSICHTEN:

@app.route('/ajax/programme', methods=['POST']) 
def retrieve_programme(): 
    if request.method == 'POST': 
     shows_list = Shows.query.all() 
     result = [] 
     for i in shows_list: 
      result.append(i.serialize(['id', 'date', 'title'])) 
     return json.dumps(result) 

Meine SHOW Modell mit der Funktion Serialize:

class Shows(db.Model): 
    __tablename__ = "shows" 

    id = Column(db.Integer, ForeignKey("programmation.id"), primary_key=True) 
    date = Column(db.DATETIME) 
    title = Column(db.VARCHAR(50)) 
    short_description = Column(db.VARCHAR(200)) 
    type = Column(db.VARCHAR(20)) 
    background_image = Column(MEDIUMBLOB) 
    content = Column(LONGTEXT) 

    def serialize(self, whatTo): 
     result = {} 
     if 'id' in whatTo: 
      result['id'] = self.id 
     if 'date' in whatTo: 
      result['date'] = str(self.date) 
     if 'title' in whatTo: 
      result['title'] = self.title 
     if 'short_description' in whatTo: 
      result['short_description'] = self.short_description 
     if 'type' in whatTo: 
      result['type'] = self.type 
     if 'background_image' in whatTo: 
      result['background_image'] = self.background_image 
     if 'content' in whatTo: 
      result['content'] = self.content 
     return result 

JQuery:

$.post("http://127.0.0.1:5000/ajax/programme", {year: '2017', semester: 1}, function(result){ 
    console.log(result); 
}); 

Ich kann also nicht glauben, dass flask und js zu diesem Punkt nicht kompatibel sind, oder dass sqlalchemy devs nicht etwas entwickelt haben. Ich muss etwas verpassen!

Danke

+2

Warum SQLAlchemy, ein ORM, müssen davon ausgehen, wie Sie Ihre Objekte serialisieren möchten? Was wenn du XML willst? Was, wenn Sie nicht einmal HTTP verwenden, sondern stattdessen in eine Binärdarstellung serialisieren möchten? Unabhängig davon ist ein gängiges Serialisierungsframework, das oft mit SQLAlchemy verwendet wird, [Marshmallow] (https://marshmallow.readthedocs.io/en/latest/). – univerio

+0

Ich stimme @univerio zu. Es ist nicht SQLAlchemy Aufgabe zu wissen, wie Sie Ihre Objekte serialisieren. Ein gängiges Paradigma ist das Hinzufügen einer 'as_dict()' -Methode zu Ihrem Modell, wo Sie die Datenpunkte explizit deklarieren, die zurückgegeben werden sollen. Dies kann leicht mit 'json.dumps' abgewickelt werden. – YellowShark

Antwort

0

Vielleicht möchten https://jsonpickle.github.io betrachten, die jede Python-Objekt serialisiert werden kann:

shows_list = Shows.query.all() 
return Response(jsonpickle.encode(shows_list), mimetype='application/json') 

Sie sollten aber so machen Ihre Instanzen vorübergehende oder abgenommen betrachten, bevor Sie mit SQLAlchemy 100% sauber zu sein . http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.make_transient

SQLAlchemy und jsonpickle beiden Geräteklassen mit versteckten Feldern der Lage sein, richtig deserialisieren, so können diejenigen, die Nutzlast verschmutzen, wenn Sie nicht um sie später zu einer Sitzung neu zu befestigen ist es egal. Wenn Ihr Anwendungsfall ist vergänglich/read-only Zugriff können Sie wie unter jenen mit Code entlang der Linien wischen:

for show in show_list: 
    sqla_session.make_transient(show) 
    show._sa_instance_state = None 
return Response(jsonpickle.encode(shows_list, unpicklable=False), 
       mimetype='application/json') 
+0

Es funktioniert wirklich gut, danke. Allerdings habe ich noch einige unerwünschte Objekte in meinen Objekten als "_proto_". Aber es ist in Ordnung, ich muss sie nicht auswählen. –

+0

Wenn es eines Ihrer Objekte ist, können Sie auch ein max_depth kwarg an jsonpickle übergeben, um anzugeben, wie tief das Diagramm serialisiert werden soll. Wenn es von einer Bibliothek instrumentiert wird und Sie sich nicht darum kümmern, können Sie es vor der Codierung löschen, genau wie _sa_instance_state oben. – TheArchitect