Fehlersuche Flask, mit Vue.js

Django, Flask, Bottle, WSGI, CGI…
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: Wenn Du die Klasse nicht hast, kannst Du sie ja schreiben. Wenn nicht für's ORM dann für die Tabelle. Oder man benutzt „reflection“ um die Tabellenklasse von SQL-Alchemy zur Laufzeit erstellen zu lassen. Ich persönlich würde aber einfach eine Klasse schreiben wie für Flask-SQLAlchemy vorgesehen.
“I am Dyslexic of Borg, Your Ass will be Laminated” — unknown
Benutzeravatar
Dennis89
User
Beiträge: 1503
Registriert: Freitag 11. Dezember 2020, 15:13

Guten Morgen und Danke.

Ich würde die Klasse schreiben, ich weis nur nicht wie ich die in meinen Code einbinden soll.
In der Doku ist das `db` - Objekt global, bei mir nicht. Ich weis nicht ob ich mich bei dem Thema besonders dumm anstelle.
Hier jetzt mal nur die Klasse für meine Cooler-Tabelle:

Code: Alles auswählen

#!/usr/bin/env python
from flask_weasyprint import render_pdf

from attrs import define, field

from cattrs import structure, unstructure
from cooler_calculation import calculate_cooler
from flask import Flask, jsonify
from flask_classful import FlaskView, request, route
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from make_template import make_template


class Base(DeclarativeBase):
    pass


class Cooler(database.Model):
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(unique=True)
    inside_diameter_outer_pipe: Mapped[float] = mapped_column()
    outside_diameter_cooling_pipe: Mapped[float] = mapped_column()
    inside_diameter_cooling_pipe: Mapped[float] = mapped_column()
    number_of_pipes: Mapped[float] = mapped_column()


@define
class App(FlaskView):
    database = field()
    user_input = None
    results = None

    @route("/get_cooler_data", methods=["GET"])
    def get_cooler_data(self):
        # TODO query database
        cooler_data = self.database.session.execute(text('SELECT * FROM Cooler'))
        if request.method == "GET":
            # TODO replace with database connection
            return self.technical_data["cooler_data"]

    @route("/get_valid_gases", methods=["GET"])
    def get_valid_gases(self):
        # TODO query database
        # valid_gas_names = self.database.session.execute()
        if request.method == "GET":
            # TODO replace with database connection
            return self.technical_data["valid_gases"]

    @route("/process_calculation", methods=["POST", "GET"])
    def index(self):
        if request.method == "POST":
            self.process_input(request.get_json())
            return jsonify(request.get_json())
        if request.method == "GET":
            data = self.merge_result_and_input()
            return render_pdf(make_template(data))

    def merge_result_and_input(self):
        user_input = unstructure(self.user_input)
        results = {"results": unstructure(self.results)}
        return user_input | results

    # def process_input(self, input_data):
    #     try:
    #         self.user_input = structure(input_data, Data)
    #     except ValueError as error:
    #         ic(error)
    #     else:
    #         gas_to_percent = {gas.name: gas.percent for gas in self.user_input.gases}
    #         self.results = calculate_cooler(
    #             self.user_input.coolers,
    #             gas_to_percent,
    #             self.user_input.general.glykohl_percent,
    #             self.user_input.general.normvolume_flow,
    #             self.user_input.general.temperature_suction_filter,
    #             self.user_input.general.suction_pressure,
    #         )


def main():
    database = SQLAlchemy(model_class=Base)
    app = Flask(__name__)
    app.config.from_object(__name__)
    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://dennis:Dennis89@127.0.0.1:3306/CoolerCalculation"
    CORS(app, resources={r"/*": {"origins": "*"}})
    database.init_app(app)
    App.register(
        app,
        route_base="/",
        init_argument=database,
    )
    app.run()


if __name__ == "__main__":
    main()
Der Code kommt so ja gar nicht am Interpreter vorbei. Hier wäre der passende Abschnitt aus der Doku dazu:
https://flask-sqlalchemy.palletsproject ... -extension

Das mit `reflection` habe ich auch gesehen, aber nicht nur du, sondern die Doku empfiehlt auch eine Klasse zu schreiben. Dann würde ich das schon auch gerne machen.

Ich hoffe ihr helft mir noch ein mal weiter.

Danke und Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: Naja wenn das in der Dokumentation auf Modulebene ist, dann muss man das halt im eigenen Programm auch machen.
“I am Dyslexic of Borg, Your Ass will be Laminated” — unknown
Benutzeravatar
Dennis89
User
Beiträge: 1503
Registriert: Freitag 11. Dezember 2020, 15:13

Ja? Mit dieser Antwort hätte ich jetzt nicht gerechnet.

Zum einen freut es mich natürlich etwas, dass ich mich doch nicht ganz sooo dumm anstelle, wie gedacht, aber das beißt sich zwar sehr mit dem was ich die letzten Jahre gelernt habe, aber dann mache ich das mal so.

Danke und Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: Modulebene ist halt für Sachen da, die in anderen, eher statischen Sprachen zur Übersetzungszeit passieren und unter “Deklaration“ fallen. Deklarieren von Datentypen und -strukturen, und genau das macht man da ja. Und der ”dynamische” Teil von dem Objekt ist genau so ”magisch” wie beispielsweise das `request` aus `flask`. Das ist ja auch ”global”, aber die Attribute enthalten nur Daten während tatsächlich eine Anfrage abgearbeitet wird *und* das *selbe* Objekt enthält in jedem Thread *andere* Werte, es sind also am Ende keine wirklich globalen Werte. Magic. Ist bei dem `db`-Objekt ja auch so, beispielsweise mit `db.session`.
“I am Dyslexic of Borg, Your Ass will be Laminated” — unknown
Benutzeravatar
Dennis89
User
Beiträge: 1503
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

danke für die Erklärung.

Ich habe die Klassen erstellt und kann jetzt auch meine Daten abfragen. Meine `row` hat jetzt Attribute und ich denke das ist nachher für das speichern und auslesen sicherlich noch geschickt. Gerade sorgt es aber wieder für graue Haare.
Ich will die Kühlerdaten auslesen und in "mein" JSON-Format stecken und an den Browser senden.
Das soll dann so aussehen:

Code: Alles auswählen

{'DN 40': {'number_of_pipes': 17, 'inside_diameter_outer_pipe': 41.1, 'outside_diameter_cooling_pipe': 6, 'inside_diameter_cooling_pipe': 4}, ...}
Die einzige Lösung auf die ich kam, sieht so aus:

Code: Alles auswählen

#!/usr/bin/env python
from attrs import define, field
from flask import Flask
from flask_classful import FlaskView, request, route
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column


class Base(DeclarativeBase):
    pass


database = SQLAlchemy(model_class=Base)


class Cooler(database.Model):
    __tablename__ = "Cooler"
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(unique=True)
    inside_diameter_outer_pipe: Mapped[float] = mapped_column()
    outside_diameter_cooling_pipe: Mapped[float] = mapped_column()
    inside_diameter_cooling_pipe: Mapped[float] = mapped_column()
    number_of_pipes: Mapped[float] = mapped_column()


class Gas(database.Model):
    __tablename__ = "Gas"
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(unique=True)


class OrderCoolerLink(database.Model):
    __tablename__ = "OrderCoolerLink"
    id: Mapped[int] = mapped_column(primary_key=True)
    cooler_id: Mapped[int] = mapped_column()
    order_id: Mapped[int] = mapped_column()
    cooling_countercurrent: Mapped[bool] = mapped_column()
    gas_humidity_after_cooler: Mapped[float] = mapped_column()
    gas_humidity_before_cooler: Mapped[float] = mapped_column()
    gas_pressure: Mapped[float] = mapped_column()
    gas_temperature_in: Mapped[float] = mapped_column()
    gas_temperature_out: Mapped[float] = mapped_column()
    temperature_cooling_fluid_in: Mapped[float] = mapped_column()
    temperature_cooling_fluid_out: Mapped[float] = mapped_column()
    number_of_cooler: Mapped[int] = mapped_column()


class OrderGasLink(database.Model):
    __tablename__ = "OrderGasLink"
    id: Mapped[int] = mapped_column(primary_key=True)
    order_id: Mapped[int] = mapped_column(unique=True)
    gas_id: Mapped[int] = mapped_column()
    percentage: Mapped[float] = mapped_column()


class Order(database.Model):
    __tablename__ = "Order"
    id: Mapped[int] = mapped_column(primary_key=True)
    glykohl_percent: Mapped[float] = mapped_column()
    normvolume_flow: Mapped[float] = mapped_column()
    suction_pressure: Mapped[float] = mapped_column()
    temperature_suction_filter: Mapped[float] = mapped_column()
    gas_id: Mapped[int] = mapped_column()
    cooler_id: Mapped[int] = mapped_column()


@define
class App(FlaskView):
    database = field()

    @route("/get_cooler_data", methods=["GET"])
    def get_cooler_data(self):
        rows = self.database.session.execute(database.select(Cooler)).scalars()
        return {
            row.name: {
                "number_of_pipes": row.number_of_pipes,
                "inside_diameter_outer_pipe": row.inside_diameter_outer_pipe,
                "outside_diameter_cooling_pipe": row.outside_diameter_cooling_pipe,
                "inside_diameter_cooling_pipe": row.inside_diameter_cooling_pipe,
            }
            for row in rows
        }


def main():
    app = Flask(__name__)
    app.config.from_object(__name__)
    app.config["SQLALCHEMY_DATABASE_URI"] = (
        "mysql+pymysql://dennis:Dennis89@127.0.0.1:3306/CoolerCalculation"
    )
    CORS(app, resources={r"/*": {"origins": "*"}})
    database.init_app(app)
    App.register(
        app,
        route_base="/",
        init_argument=database,
    )
    app.run()


if __name__ == "__main__":
    main()
Das kann doch aber nicht der Sinn sein? Wenn ich jetzt eine Reihe hinzufüge/ändere muss ich die mitten im Code auch noch ändern.
Ich finde zwar in der Doku wie man die `mapped_column` erstellt und was man da alles so angeben kann, aber mir fehlt der Punkt, wie ich jetzt nach der Abfrage mit den Objekten/dem Objekt umgehen kann:
https://docs.sqlalchemy.org/en/20/orm/m ... ped_column
https://docs.sqlalchemy.org/en/20/orm/d ... tive-table

Das ist immer wieder mein Punkt, das ich Probleme habe, die ich mit der Doku nicht lösen kann. Es war auch schon öfters so, dass das schon drin stand, nur ich nicht den Begriff wusste nach dem ich suchen soll oder ähnliches.

Ich würde jetzt echt gerne bei SQLAlchemy bleiben, bitte helft mir das ich irgendwie den Einstieg schaffe.

Vielen Dank und Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
grubenfox
User
Beiträge: 593
Registriert: Freitag 2. Dezember 2022, 15:49

ich habe da diesen hier gefunden (keine Ahnung ob es hilft):
https://www.slingacademy.com/article/sq ... into-json/
Benutzeravatar
grubenfox
User
Beiträge: 593
Registriert: Freitag 2. Dezember 2022, 15:49

Wobei ich aktuell gerade das Problem nicht sehe: wenn es eine definierte Schnittstelle gibt, dann muss die an zwei Stellen in Code umgesetzt werden: auf der Sender-Seite und auf der Empfänger-Seite.
Ändert sich was an der Definition (z.B. neues zusätzliches Feld), dann müssen beide Seiten angepasst werden...
Benutzeravatar
Dennis89
User
Beiträge: 1503
Registriert: Freitag 11. Dezember 2020, 15:13

Danke für die Antwort.

Das Problem ist, das ich im Python-Code zwei mal die gleiche Änderung machen müsst, weil ich habe einmal die Klasse `Cooler` die die Struktur enthält und dann meine manuelle Umwandlung in der Funktion `get_cooler_data`. Die Bezeichnungen habe ich schon in der Klasse stehen und schreibe sie jetzt noch mal von Hand in die Funktion. Das stört mich.

Auch `_asdict()` was ich bei meiner "alten" Abfrage mit `text()` drin hatte, gibt mir nichts aus, das ich umwandeln könnte. Also sowas

Code: Alles auswählen

rows = self.database.session.execute(database.select(Cooler)).all()
for row in rows:
    print(row._asdict())
ergibt mir

Code: Alles auswählen

{'Cooler': <Cooler 1>}
{'Cooler': <Cooler 2>}
{'Cooler': <Cooler 3>}
{'Cooler': <Cooler 4>}
{'Cooler': <Cooler 5>}
{'Cooler': <Cooler 6>}
{'Cooler': <Cooler 7>}
{'Cooler': <Cooler 8>}
{'Cooler': <Cooler 9>}
{'Cooler': <Cooler 10>}
{'Cooler': <Cooler 11>}
Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
grubenfox
User
Beiträge: 593
Registriert: Freitag 2. Dezember 2022, 15:49

Dann eine Liste der Bezeichnungen in der Klasse speichern (möglicherweise in der Klassenvariablen __slots__, aber ob das sinnvoll ist wage ich jetzt nicht zu beurteilen) und später dann immer über die Liste iterieren und mit setattr und getattr arbeiten...
Benutzeravatar
grubenfox
User
Beiträge: 593
Registriert: Freitag 2. Dezember 2022, 15:49

Dann stehen die Bezeichnungen aber wohl doppelt in der Klasse (einmal in der Liste, das zweite Mal als `mapped_column`). Auch nicht schön.
Mit dir() würde man eine Liste der Attribute der Klasse bekommen. Aber da ist dann relativ viel Beifang dabei. Da müsste man noch sehen dass man wirklich nur die gewünschten Namen erhält.
Das komische Zeug mit `mapped_column()`... kann man da was werden? Sind diese Elemente dann vom Typ 'mapped_column' oder eher 'float', 'int' und so weiter?
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

@Dennis89: das liegt daran, dass Du Sqlalchemy immer noch falsch benutzt. Du gehst immer noch auf die low-level Funktion execute und select, und da dort mit einer Abfrage mehrere Tabellen zurückgegeben werden können, besteht eine Reihe natürlich aus einem Objekt das die Tabellen über ihren Namen zugreifbar macht.
Richtig wäre

Code: Alles auswählen

rows = database.session.query(Cooler)
Benutzeravatar
Dennis89
User
Beiträge: 1503
Registriert: Freitag 11. Dezember 2020, 15:13

Danke für die Antworten.
@grubenfox die Werte sind von den Typen, die ich als Typ-Annotation angegeben habe. Ob es für `mapped_column' etwas geschickteres gibt, bzw. ich habe in der Doku (siehe Link oben) nichts gefunden, was mir helfen könnte.

@Sirius
In der Doku steht folgendes:
You may see uses of Model.query to build queries. This is an older interface for queries that is considered legacy in SQLAlchemy. Prefer using db.session.execute(db.select(...)) instead.

See Modifying and Querying Data for more information about queries.
In dem weiterführenden Link wird wieder auf `execute` verwiesen.

Ich muss aber auch ehrlich sagen, dass ich das gerade erst gesehen habe, als ich nach deiner Antwort in der Doku gesucht habe.

Wenn ich jetzt folgendes machen:

Code: Alles auswählen

rows = self.database.session.query(Cooler)
for row in rows:
    print(row)
Dann erhalte ich wieder meine Objekte:

Code: Alles auswählen

<Cooler 1>
<Cooler 2>
<Cooler 3>
<Cooler 4>
<Cooler 5>
<Cooler 6>
<Cooler 7>
<Cooler 8>
<Cooler 9>
<Cooler 10>
<Cooler 11>
Die kein `_asdict()` kennen.

Hm da hat sich vermutlich etwas in SQLAlchemy geändert?

Grüße und Danke
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

`sqlalchemy.inspect()` kann einem alles mögliche über SQLAlchemy-Datentypen verraten. Zum Beispiel bei einer Mapper-Klasse die Spalteninformationen. Namen, Typen, und so weiter.
“I am Dyslexic of Borg, Your Ass will be Laminated” — unknown
Benutzeravatar
Dennis89
User
Beiträge: 1503
Registriert: Freitag 11. Dezember 2020, 15:13

Guten Morgen,

danke für die Info. Ich habe das ausprobiert, in einem Test-Programm ohne `Flask-SQLAlchemy` in dem ich `create_engine` benutze kann ich da `inspect` benutzen. Zum Beispiel:

Code: Alles auswählen

def main():
    engine = create_engine("mysql+pymysql://dennis:Dennis89@127.0.0.1:3306/CoolerCalculation", echo=True)
    inspector = inspect(engine)
    print(inspector.get_columns("Cooler"))
gibt:

Code: Alles auswählen

[{'name': 'id', 'type': INTEGER(display_width=11), 'default': None, 'comment': None, 'nullable': False, 'autoincrement': True}, {'name': 'name', 'type': VARCHAR(length=20), 'default': None, 'comment': None, 'nullable': True}, {'name': 'inside_diameter_outer_pipe', 'type': FLOAT(), 'default': None, 'comment': None, 'nullable': True}, {'name': 'outside_diameter_cooling_pipe', 'type': FLOAT(), 'default': None, 'comment': None, 'nullable': True}, {'name': 'inside_diameter_cooling_pipe', 'type': FLOAT(), 'default': None, 'comment': None, 'nullable': True}, {'name': 'number_of_pipes', 'type': FLOAT(), 'default': None, 'comment': None, 'nullable': True}]
MIt `Flask-SQLAlchemy` habe ich kein `create_engine` und habe nichts gefunden, das ich `inspect` übergeben kann um das gleiche Ergebnis zu erhalten. Aber auch unabhängig davon, ich hätte erwartet, dass man das viel lesbarer und mit weniger Code machen kann oder braucht man sowas eigentlich nie? Gibt es einen besseren/einfacheren Weg, die Daten an den Browser zu senden?
Auf der Webseite soll man halt in einem Dropdown-Menü `Cooler.name` auswählen können und die zugehörigen Daten werden dann automatisch angezeigt. Mit meiner JSON-Struktur, die ich bis jetzt übergeben hatte, funktioniert das. Ich habe aber das Gefühl, dass der Code den ich schreiben muss um die Struktur wieder zu erhalten, entweder unverständlich wird oder das ich vieles doppelt schreibe.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: `inspect()` kann man ja so einiges übergeben. Zum Beispiel auch die `Cooler`-Klasse. Wo man von einem `Cooler`-Objekt ja mit `type()` dran kommt, wenn man da etwas generisches schreiben möchte was einfach ein Mapper-Objekt bekommt.

Es hilft halt nichts bei solchen Konvertierungen muss man entweder etwas Generisches schreiben, oder manuell Attribut auf Attribut abbilden.
“I am Dyslexic of Borg, Your Ass will be Laminated” — unknown
Benutzeravatar
Dennis89
User
Beiträge: 1503
Registriert: Freitag 11. Dezember 2020, 15:13

Hm okay. Ich hab den Teil jetzt mal mit einem `# TODO` versehen und will das noch einmal aufgreifen, wenn ich den Rest zusammen habe und auch hoffentlich mal wieder mehr Zeit dafür habe. Die beteiligten Personen wissen zwar, das ich mir hier einiges aneignen muss und das auch in meiner Freizeit mache, aber ich würde dann schon gerne den nächsten Schritt präsentieren um auch zu sehen, wie es mit diesem Projekt weiter geht.

Ich schau mal wie weit ich mit dem speichern in die Datenbank komme und melde mich dann wieder.

Vielen Dank und Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
Dennis89
User
Beiträge: 1503
Registriert: Freitag 11. Dezember 2020, 15:13

Hello again,

ich bin am verzweifeln, ich komme mit der erstellten Tabellen/Tabellenstruktur nicht wirklich klar.
Damit ihr nicht hier ewig im Thread suchen müsst, so sehen meine Tabellen aus:

Code: Alles auswählen

class Cooler(database.Model):
    __tablename__ = "Cooler"
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(unique=True)
    inside_diameter_outer_pipe: Mapped[float] = mapped_column()
    outside_diameter_cooling_pipe: Mapped[float] = mapped_column()
    inside_diameter_cooling_pipe: Mapped[float] = mapped_column()
    number_of_pipes: Mapped[float] = mapped_column()


class Gas(database.Model):
    __tablename__ = "Gas"
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(unique=True)


class OrderCoolerLink(database.Model):
    __tablename__ = "OrderCoolerLink"
    id: Mapped[int] = mapped_column(primary_key=True)
    cooler_id: Mapped[int] = mapped_column()
    order_id: Mapped[int] = mapped_column()
    cooling_countercurrent: Mapped[bool] = mapped_column()
    gas_humidity_after_cooler: Mapped[float] = mapped_column()
    gas_humidity_before_cooler: Mapped[float] = mapped_column()
    gas_pressure: Mapped[float] = mapped_column()
    gas_temperature_in: Mapped[float] = mapped_column()
    gas_temperature_out: Mapped[float] = mapped_column()
    temperature_cooling_fluid_in: Mapped[float] = mapped_column()
    temperature_cooling_fluid_out: Mapped[float] = mapped_column()
    number_of_cooler: Mapped[int] = mapped_column()


class OrderGasLink(database.Model):
    __tablename__ = "OrderGasLink"
    id: Mapped[int] = mapped_column(primary_key=True)
    order_id: Mapped[int] = mapped_column(unique=True)
    gas_id: Mapped[int] = mapped_column()
    percentage: Mapped[float] = mapped_column()


class Order(database.Model):
    __tablename__ = "Order"
    id: Mapped[int] = mapped_column(primary_key=True)
    glykohl_percent: Mapped[float] = mapped_column()
    normvolume_flow: Mapped[float] = mapped_column()
    suction_pressure: Mapped[float] = mapped_column()
    temperature_suction_filter: Mapped[float] = mapped_column()
    gas_id: Mapped[int] = mapped_column()
    cooler_id: Mapped[int] = mapped_column()
Die JSON-Struktur die mir der Browser schickt, sieht so aus:

Code: Alles auswählen

{'gases': [{'id': 3, 'name': 'Air', 'percent': 100}], 'coolers': [{'id': 10, 'number_of_pipes': 310, 'outside_diameter_cooling_pipe': 6, 'inside_diameter_cooling_pipe': 4, 'inside_diameter_outer_pipe': 211.1, 'temperature_cooling_fluid_in': 20, 'temperature_cooling_fluid_out': 50, 'gas_temperature_in': 200, 'gas_temperature_out': 50, 'gas_pressure': 5, 'gas_humidity_before_cooler': 0, 'gas_humidity_after_cooler': 0, 'name': 'DN 200', 'cooling_countercurrent': True, 'number_of_cooler': 1}], 'order': {'order_number': '239035', 'normvolume_flow': 500, 'glykohl_percent': 0, 'suction_pressure': 1, 'temperature_suction_filter': 20}}
Ich kann die mit `structure()` noch in ein Data-Objekt wandeln, so weit so gut.
Wenn ich damit starte, erst die Kühlerwerte in die Tabelle `OrderCoolerLink` zu schreiben, dann kann ich das nicht auf einen Rutsch machen, weil ich keine `order_id` habe. Na gut, dann schreibe ich erst alles in `Order`, ich habe aber noch keine `gas_id` und keine `cooler_id`.

Kann ich die `order_id` von Hand vergeben und dafür die Auftragsnummer verwenden, die der User angibt? Dann könnte ich `OrderGasLink` und `OrderCoolerLink` befüllen, dann die vergebene ID von beiden abfragen und dann damit `Order` befüllen. Oder? 🤯

Vielen Dank und Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum hat eine Order eine gas_id und eine cooler_id?

Der logische Ablauf ist doch, Du legst eine neue Order an, bekommst dadurch eine ID, dann suchst Du die passenden Gase und Cooler aus den Tabellen raus und legst die Link-Einträge dafür an.
Benutzeravatar
Dennis89
User
Beiträge: 1503
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

danke für den Hinweis, ich habe noch mal die vorherigen Posts durch gelesen und vermutlich habe ich was falsch verstanden.
Habe das jetzt umgebaut und die Funktion, um die Werte zu speichern funktioniert auch und sieht so aus:

Code: Alles auswählen

@route("/save_input_data", methods=["POST"])
    def save_input_data(self):
        input_data = structure(request.get_json(), Data)
        order = Order(
            glykohl_percent=input_data.order.glykohl_percent,
            normvolume_flow=input_data.order.normvolume_flow,
            suction_pressure=input_data.order.suction_pressure,
            temperature_suction_filter=input_data.order.temperature_suction_filter,
        )
        self.database.session.add(order)
        self.database.session.commit()
        for cooler in input_data.coolers:
            order_cooler_link = OrderCoolerLink(
                cooler_id=cooler.id,
                order_id=order.id,
                cooling_countercurrent=cooler.cooling_countercurrent,
                gas_humidity_after_cooler=cooler.gas_humidity_after_cooler,
                gas_humidity_before_cooler=cooler.gas_humidity_before_cooler,
                gas_pressure=cooler.gas_pressure,
                gas_temperature_in=cooler.gas_temperature_in,
                gas_temperature_out=cooler.gas_temperature_out,
                temperature_cooling_fluid_in=cooler.temperature_cooling_fluid_in,
                temperature_cooling_fluid_out=cooler.temperature_cooling_fluid_out,
                number_of_cooler=cooler.number_of_cooler,
            )
            self.database.session.add(order_cooler_link)
            self.database.session.commit()

        for gas in input_data.gases:
            order_gas_link = OrderGasLink(
                order_id=order.id,
                gas_id=gas.id,
                percentage=gas.percent
            )
            self.database.session.add(order_gas_link)
            self.database.session.commit()
Soweit schon mal ganz cool.(ein Rückgabewert fehlt der Funktion noch, den baue ich gleich als nächstes noch ein) Wenn ihr das mit dem speichern auch so machen würdet, dann baue ich jetzt die nächste Funktion, die die Datenbank ausliest und die eingetragenen Werte an den Browser sendet.

Viele Grüße und noch mal danke für die Unterstützung
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Antworten