Home » Uncategorized » Web App with Flask (Python) on PostgresSQL

Web App with Flask (Python) on PostgresSQL

The following is a fully functional Web App implemented in Flask (Python) profiding CRUD operations on a PostgresSQL DB.

Code

templates/index.html:

{% for d in data %} : The HTML-Templating, die benutzt wird um auf Datenbasis (Parameter-Basis) HTML (DOM) zu generieren ist: Jinja

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Tasks</title>
    <style>
        .hidden {
            display : none;
        }
    </style>
</head>
<body>

    <div>This page (together with its back-end) demonstrates a minimal Web App that uses different technologies to query (toDo) items from the backend (and DB):</div>
    <h2>ADD with HTML Form Submit</h2>
    <div>Demonstrates add DB operation by usage of HTML old fashioned form. The new results are displayed by usage of the redirect to the index page (the page at '/') which you typically would open first and that initially queries all toDos.</div><br>
    <div>Insert todo description to add:</div>
    <form action="/todos/create" method="POST">
        <input type="text" name="description" />
        <input type="submit" value="create" />
    </form>
    <ul>
        {% for d in data %}
        <li>{{ d.description }}</li>
        {% endfor %}
    </ul>


    <h2>ADD with Ajax Single Page Version</h2>
    <div>Demonstrates add DB operation by usage of Ajax request. Simulation of single page app: The added entry is added by DOM manipulation.</div><br>
    <div>Insert todo description to add:</div>
    <div id="error" class="hidden">Something went wrong!</div>
    <form id="form2">
        <input type="text" id="description" />
        <input type="submit" value="create" />
    </form>
    <ul id = "todoListByAjax">
        {% for d in data %}
        <li>{{ d.description }}</li>
        {% endfor %}
    </ul>
    <script>
        document.getElementById('form2').onsubmit = function (e) {
            console.log('submit handler for Ajax case executing');
            e.preventDefault();
            fetch('todos/ajaxCreate', {
                method : 'POST',
                body : JSON.stringify({
                    'description' : document.getElementById('description').value
                }),
                headers : {
                    'Content-Type' : 'application/json'
                }
            }).then(function(response){
                return response.json()
            }).then(function (jsonResponse) {
                console.log('HPS received');
                console.log(jsonResponse);
                const liItem = document.createElement('LI');
                liItem.innerHTML = jsonResponse['description'];
                document.getElementById('todoListByAjax').appendChild(liItem);
                document.getElementById('error').classList = 'hidden';
            }).catch(function (reason) {
                document.getElementById('error').classList = '';
            });
        }

        var xhttp = new XMLHttpRequest();

        description = document.getElementById("description").value;

        xhttp.open("GET", "/todos/create?description=" + description);

        xhttp.send();
    </script>

    <h2>Delete all todo items</h2>
    <form action="/todos/deleteAll" method="GET">
        <input type="submit" value="delete all" />
    </form>

    <h2>XMLHttpRequest Version</h2>
    <div>Demonstrates select/filter DB operation by usage of XMLHttpRequest. Simulation of single page app: The found entry is added to the result node by DOM manipulation.</div><br>
    <div>Insert todo description to search for:</div>
    <form id="form3">
        <input type="text" id="description3" />
        <input type="submit" value="search" />
    </form>
    <h5>Result:</h5>
    <div id="responsefield"/>
    <script>
        function load(url, callback) {
            var xhr = new XMLHttpRequest();

            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    callback(xhr.response);
                }
            }
            xhr.open('GET', url, true);
            xhr.send('');
        }
        document.getElementById('form3').onsubmit = function (e) {
            console.log('submit handler for XMLHttpRequest case executing');
            const filterVal = document.getElementById('description3').value;
            e.preventDefault();
            load('todos/getWithXmlHttpRequestExample?description=' + filterVal, function(resp){
                const respField = document.getElementById('responsefield');
                respField.innerText = resp;
            })
        }
    </script>

</body>
</html>

app.py:

from flask import Flask, render_template, request, redirect, url_for, jsonify, abort
from flask_sqlalchemy import SQLAlchemy
import sys

app = Flask(__name__) #Tells Flask that this file is the actual app runner
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:admin@localhost:5432/todoDB'

db = SQLAlchemy(app)

class Todo(db.Model):
    __tablename__ = 'todos'
    id = db.Column(db.Integer, primary_key=True)
    description = db.Column(db.String(), nullable=False)

    def __repr__(self):
        return f'<Todo {self.id} {self.description}>'

#create all defined entities:
db.create_all()

def db_insert(description):
    is_error = False
    try:
        todo_in = Todo(description = description)
        db.session.add(todo_in)
        db.session.commit()
    except:
        is_error = True
        db.session.rollback()
        print(sys.exc_info())
    finally:
        db.session.close()

    return is_error

@app.route('/')
def index():
    return render_template('index.html', data=Todo.query.all())

@app.route("/todos/create", methods=['POST'])
def create_todo():
    description = request.form.get('description', 'Null Default Task')
    is_error = db_insert(description)
    if is_error:
        abort (400)
    else:
        return redirect(url_for('index'))

@app.route("/todos/ajaxCreate", methods=['POST'])
def create_todo_via_ajax():
    print('Method create_todo_via_ajax() start ')
    description = request.get_json()['description']
    is_error = db_insert(description)
    todo_in = Todo(description = description)

    if is_error:
        abort (400)
    else:
        print('Method create_todo_via_ajax(): committed')
        return jsonify({
            'description' : todo_in.description
        })

@app.route("/todos/getWithXmlHttpRequestExample", methods=['GET'])
def get_todo_via_xml_http_request_example():
    data=Todo.query.filter(Todo.description==request.args.get('description')).all()
    try:
        if len(data) > 0:
            print("returning: " + str(data[0].id) + " " + data[0].description)
            return "Found entry with ID: '" + str(data[0].id) + "': '" + data[0].description + "'"
        else:
            return "No data found"
    except:
        return "An error occured"

@app.route("/todos/deleteAll", methods=['GET'])
def remove_all():
   Todo.query.delete()
   db.session.commit()
   return render_template('index.html', data=Todo.query.all())

Project structure:

project_main
   app.py
   templates
      index.html

Starten der Applikation


Auf Windows

set FLASK_APP=.\project_main\app.py
set FLASK_DEBUG=True
flask run

Postgres DB muss aufgesetzt sein (siehe links unten)

Siehe auch


Hinterlasse einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.