React JS – Einführung
Diese wunderbare Einführung in das React JS Gui Framework macht es völlig unnötig hier noch mehr zu schreiben.
Dass ich trotzdem noch etwas Schreibe ist mehr als Mittel gedacht für mich selbst einig Merkpunkte nochmals zu recapitulieren.
Building Blocks
Importieren von
import React from 'react';
import ReactDOM from 'react-dom';
GUI-Compoent-Modell
Nun können React Componenten als Klassen angelegt werden:
class Square extends React.Component {
render() {
return (
<button className="square" onClick={function() { console.log('click'); }}>
{this.props.value}
</button>
);
}
}
class Board extends React.Component {
renderSquare(i) {
return (<Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />);
}
render() {
return (
<div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
Obiger Code zeigt die definition von zwei Componenten (Board und Square). Was durch diese Component im GUI angezeigt wird ist dadurch definiert, was ihre render Methode zurück gibt.
Dieses Rückgabe-Object wird auch React Element genannt.
Im obigen Beispiel wird das React Element mittels JSX Notation beschrieben, welche HTML imitiert.
Die Mitgabe von Sub-Elementen (-Componenten) and den Parser geschieht im Beispiel mit:
return (<Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />);
Die Component-Sub-Klasse (im Beispiel ‚Square‘) wird also wie ein HTML-Tag referenziert!
Parameter-Übergabe und Modell-GUI-Synchronisation
Parameter-Übergabe
Wird eine Sub-Component z.B. so ins GUI einbezogen …
return (<Square meinWert={myVar}>
dann kann sie nachher in der Sqare-Component so ausgelesen werden:
this.parms.meinWert
Status und Modell-GUI-Synchronisation
Status Definition
Der von React verwaltete State muss im Constructor definiert werden:
class Game extends React.Component {
constructor(props){
super(props);
this.state = {
meineVar: 'Mein Wert'
};
}
Beachte:
super(props)
ist zu programmieren!- Der State einer Component ist privat!
Status Update
Mittels this.setState()
wird der State in der render Methode vom Programmierer nachgeführt. React führt automatisch die States der Unter-Komponenten nach.
this.setState({meineVar: 'Hallo Welt'});
In Flask: JavaScript als File auslagern
Symptom: Dieser seltsame Fehler:
sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) FEHLER: ungültige Eingabesyntax für Typ integer: »app.js«
LINE 3: WHERE todolists.id = ‚app.js‘
Lösung: Korrektes Referenzieren des Javascript-Files in einer Flask-Applikation:
In Flask apps stehen JavaScript und CSS files standardmässig in einem static
genannten directory neben dem templates
Directory, das die HTML templates enthält.
Im HTML-File wird ein File (z.B. Namens app.js) dann so referenziert:<script src="{{url_for('static', filename='app.js')}}"></script>
Achtung: Das Scripts-Tag muss am Ende des Bodies stehen.
Oracle SQL – Know how
Concatenate the different row values of the same group into on row per group.
LISTAGG Function, see: Sql PIVOT and string concatenation aggregate
SQL Pivot
Referenzen
Oracle PIVOT – Introduction to Oracle PIVOT
clause
SQL Pivot: Converting Rows to Columns
Sql PIVOT and string concatenation aggregate (Schwierig :-))
Kurz-Erklärung
SQL Pivot kann benutzt werden um Gruppierungen innerhalb eines Resultat-Sets zu machen und pro Gruppe zusätzliche Kolonnen zu extrahieren.
Hätten wir z.B. ein statement:
SELECT MONAT, REGENMENGE FROM REPORT;
Monat | Regenmenge | |
---|---|---|
1 | 100 | |
2 | 212 | |
3 | 322 | |
… | … | |
Wenn man daraus dieseses Format erstellen möchte:
Januar | Februar | März | April | … | ||
100 | 212 | 322 |
… würde man dies mit folgendem Pivot-Statement erreichen:
SELECT MONAT, REGENMENGE FROM REPORT
PIVOT max(REGENMENGE) -- Aggregatsfunktion fuer mehrere werte fuer denselben Monat
FOR MONAT
IN ( '1' as JANUAR, '2' as FEBRUAR, '3' as MÄRZ, '4' as APRIL, ...)
WordPress Error: Aktualisierung fehlgeschlagen. Die Antwort ist keine gültige JSON-Antwort.
Workpress weigert sich, den Beitrag zu speicher. Fehlermeldung:
The error „Aktualisierung fehlgeschlagen. Die Antwort ist keine gültige JSON-Antwort.“
Gefundene Lösung:
Es hat sich in jenem Fall herausgestellt, dass WordPress mit dem Text 'import java.io. File'
seine Mühe hatte (weshalb ich auch diesen Eintrag nicht speichern könnte würde ich eben diesen Import richtig schreiben 🙂
Java JDBC program to execute update statements from a file
package db.werkzeuge;
import java. io.File; //!!Wrong written because if not WordPress hesitates to save this.
import java.io.IOException;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.sql.*;
class DBLoad {
public static void main (String[] args) {
try {
String startTime = time();
System.out.println("Started at: " + startTime);
String url = "jdbc:oracle:thin:@myserver.ch:12121:STMP01";
Connection conn = DriverManager.getConnection(url,"user1","password1");
int i = 1;
int iSuccess = 0;
for(String stmt : readStatements("in/file_with_update_statements.sql")){
try {
execute(conn, stmt);
iSuccess++;
}catch(Exception e){
System.out.println("ERROR: Could not update row nbr " + i + ". Statement was: " + stmt);
System.out.println(e);
}
i++;
}
System.out.println("\nEND: Updated " + iSuccess + " records on DB.");
System.out.println("Start time: " + startTime + " / " + " Finished at: " + time());
// conn.commit();
conn.close();
} catch (Exception e) {
System.err.println("Got an exception! ");
System.err.println(e.getMessage());
}
}
private static List<String> readStatements(String fileName){
File file = new File(DBLoad.class.getClassLoader().getResource(fileName).getFile());
try (Stream<String> stream = Files.lines(file.toPath())) {
return stream.filter(s -> !s.startsWith("--")).map(s -> s.replaceAll(";", "")).collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
}
return new ArrayList<>();
}
private static void execute(Connection conn, String stmt) throws SQLException {
System.out.print("X");
Statement st = conn.createStatement();
st.executeUpdate(stmt);
}
public static String time() {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
return dtf.format(now);
}
}
Remark: ‚import java. io.File‚ habe ich absichtlich falsch geschrieben, da sonst WordPress sich weigern würde den Beitrag abzuspeichern. Fehlermeldung: „Aktualisierung fehlgeschlagen. Die Antwort ist keine gültige JSON-Antwort.“
Refernce used: Alvin Alexanders Blog über JDBC …
SQLAlchemy/Python DB-Manipulation basierend of ORM Model
Wenn z.B. ein Python File vorliegt, dass DB-Connectivity und Entitätenmodell definiert:
(Python interpreter wurde aus dem Verzeichnis mit dem app.py gestartet. FLASK_APP Environmentvariable zeigte auch auf das app.py File.)
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:admin@localhost:5432/todoDB'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class TodoList(db.Model):
__tablename__ = 'todolists'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), nullable=False)
todos = db.relationship('Todo', backref='list', lazy=True)
def __repr__(self):
return f'<TodoList {self.id} {self.name}>'
class Todo(db.Model):
__tablename__ = 'todos'
id = db.Column(db.Integer, primary_key=True)
description = db.Column(db.String(), nullable=False)
completed = db.Column(db.Boolean, nullable=False, default=False)
list_id = db.Column(db.Integer, db.ForeignKey('todolists.id'), nullable=False)
def __repr__(self):
return f'<Todo {self.id} {self.description}, list {self.list_id}>'
Beachte: Der Foreign Key heisst ‚list_id‚, die ‚backref‘ wird aber mit ‚list‚ angegeben und auch das TodoList-Parent-Objekt wird (siehe unten) an die Referenz Todo.list angehängt.
Dann können mittels Python auf der Commandline folgendermassen Entitäten erstellt und gespeichert werden:
C:\tmp\Python_Workspace1\step4-todoapp-crud-lists>python
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 16:30:00) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from app import db, Todo, TodoList
>>> list1 = TodoList(name='Haushalt')
>>> todo1 = Todo(description='putzen')
>>> todo2 = Todo(description='kochen')
>>> todo1.list=list1
>>> todo2.list=list1
>>> list1.id=3
>>> db.session.add(list1)
>>> db.session.commit()
Resultat:
todoDB=# select * from todos;
id | description | completed | list_id
----+-------------+-----------+---------
6 | putzen | f | 3
7 | kochen | f | 3
(5 Zeilen)
todoDB=# select * from todolists;
id | name
----+---------------
3 | Haushalt
(3 Zeilen)
todoDB=#