Compare commits

...

6 Commits

Author SHA1 Message Date
0fd7679ac7 register funktion 2024-08-08 11:55:21 +02:00
41a1bb3530 Linker Block je nach Login Status 2024-08-06 20:11:36 +02:00
751c67c05b File for classes created.
class to check for logged in user created
2024-08-06 19:06:09 +02:00
0e55fd55fd readme eingefügt 2024-08-05 20:46:07 +02:00
e7e70daec0 funktionierendes Grundprojekt 2024-08-05 20:43:29 +02:00
1231787e08 Datenbank Model ausgelagert 2024-08-05 17:48:09 +02:00
22 changed files with 624 additions and 303 deletions

0
Icon Normal file
View File

30
app.py
View File

@ -1,30 +0,0 @@
from flask import Flask, render_template, request, jsonify
from flask_sqlalchemy import SQLAlchemy
# Initialize the database object
db = SQLAlchemy()
def create_app():
# Create a new Flask application instance
app = Flask(__name__)
# Configure the SQLite database URI for the application
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mydatabase.db'
# Disable tracking modifications to SQLAlchemy objects
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Initialize the database object with the Flask application instance
db.init_app(app)
# Import and initialize models, then create tables within the app context
with app.app_context():
from models import User # Assuming there is a file named models.py containing the User model
from utils import check_and_create_tables # Assuming there is a file named utils.py containing the check_and_create_tables function
check_and_create_tables(db) # Call the function to ensure tables are created if they don't exist
return app
if __name__ == '__main__':
# Create and run the Flask application instance with debugging enabled
app = create_app()
app.run(debug=True)

View File

@ -1,3 +0,0 @@
class Config:
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///learn.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

22
lernplattform/__init__.py Normal file
View File

@ -0,0 +1,22 @@
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
# Initialize a new Flask app instance with the name of the current module (main).
app = Flask(__name__)
# Set the secret key for this application. This is required for session management in Flask.
# The secret key should be a cryptographically secure random value, and it's used to sign cookies.
# For more information: https://flask.palletsprojects.com/en/2.3.x/config/#SECRET_KEY
app.secret_key = 'faab0674dd8d9a4554cbeb53da2dad1414cc4c64b778e282da0b1662df7e0f85'
# Configure the database URI for SQLAlchemy. Here, it uses an SQLite database named 'learn.db'.
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///learn.db'
# Disable tracking modifications to the database, which is not necessary in this case and can improve performance.
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Initialize SQLAlchemy with the Flask app instance for database management.
db = SQLAlchemy(app)
# Import the routes module from the lernplattform package, which is assumed to be in the same directory.
import lernplattform.routes

6
lernplattform/app.py Normal file
View File

@ -0,0 +1,6 @@
from lernplattform import app
from lernplattform.models import initialize_database
if __name__ == '__main__':
initialize_database() # Initialisiere die Datenbank beim Start der Anwendung
app.run(debug=True)

82
lernplattform/classes.py Normal file
View File

@ -0,0 +1,82 @@
from flask import Flask, request, session, make_response, redirect, url_for
from werkzeug.security import generate_password_hash, check_password_hash
from lernplattform import app, db
from lernplattform.models import User
import random
import string
def generate_random_string(length=8):
characters = string.ascii_letters + string.digits
random_string = ''.join(random.choice(characters) for _ in range(length))
return random_string
class login():
"""
A class for handling user login functionality.
Attributes:
user_name (str): The username to be checked for authentication.
Methods:
__init__(self, user_name=None): Initializes the login object with a given user name.
check(user_name): A static method that checks if the provided user name is valid.
login(self): Prints "Login" to indicate that the login method has been called.
"""
def __init__(self, user_name=None, login_data=None):
self.user_name = user_name # Initialize the user name attribute for the login class
def check_logged_in():
if request.cookies.get('username') is None:
session['logged_in'] = False
session['username'] = 'Gast'
return False # Return False if the user name is not provided
else:
session['logged_in'] = True
session['username'] = request.cookies.get('username')
session['userid'] = request.cookies.get('userid')
return True # Otherwise, return True indicating a valid user name
def login(login_data):
# get password from db
user = User.query.filter_by(username = login_data.get('username')).first()
if user and check_password_hash(user.password, login_data.get('password')):
if not user.email_check == "":
return False
session['userid'] = user.id
session['username'] = user.username
session['logged_in'] = True
if login_data['remember'] == 'on':
resp = make_response(redirect(url_for('index')))
resp.set_cookie('userid', user.id)
resp.set_cookie('username', user.username)
return True
else:
return False
def logout():
resp = make_response(redirect(url_for('index')))
resp.set_cookie('username', '', expires=0)
resp.set_cookie('userid', '', expires=0)
session['logged_in'] = False
return resp
def register(request):
username = request.form.get('username')
email = request.form.get('email')
password = request.form.get('password')
hashed_password = generate_password_hash(password, method='pbkdf2:sha256')
if User.query.filter_by(username = username).first():
return False # Return False if the user name is already in use
else:
random_string = generate_random_string()
user = User(username = username, email = email, password = hashed_password, email_check = random_string)
db.session.add(user)
db.session.commit()
return True

36
lernplattform/models.py Normal file
View File

@ -0,0 +1,36 @@
from lernplattform import db
from sqlalchemy.sql import func
# Define a User model that represents the user table in the database
class User(db.Model):
"""
A class representing the user table in the database.
Attributes:
id (int): The unique identifier for each user, set as the primary key.
username (str): The username of the user, must be unique and cannot be null.
email (str): The email address of the user, must be unique and cannot be null.
password (str): The hashed password of the user, cannot be null.
email_check (str): A string field to store email verification status.
register_date (datetime): The date and time when the user registered, defaults to the current timestamp.
Methods:
__repr__(): Returns a string representation of the User object in the format "User('username', 'email')".
"""
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(60), nullable=False)
email_check = db.Column(db.String(10), nullable=True)
register_date = db.Column(db.DateTime, nullable=False, default=func.now())
# Magic method to represent the object as a string when printed or used in string context
def __repr__(self):
return f"User('{self.username}', '{self.email}')"
# Function to initialize the database by creating all tables defined in models if they do not exist
def initialize_database():
from lernplattform import app
# Create an application context before running operations on the database within this function
with app.app_context():
db.create_all()

53
lernplattform/routes.py Normal file
View File

@ -0,0 +1,53 @@
from flask import render_template, url_for, flash, redirect, jsonify, request, session
from lernplattform import app
from lernplattform.models import User
from lernplattform import db
from lernplattform.classes import login
@app.route('/')
def index():
"""
Renders the main page of the application.
This function checks if a user is logged in by checking for a 'user_name' cookie.
If the user is logged in, it retrieves the username from the database using the cookie value.
If not, it defaults to 'Gast'. The main page is then rendered with the current username.
Returns:
A rendered HTML template with the current username.
"""
login.check_logged_in()
# Render the main page with the current username
return render_template('index.html', page='index', user_name=session['username'])
@app.route('/login', methods=['GET', 'POST'])
def userlogin():
if request.method == 'POST':
#data = request.form
if request.form.get('form_id') == 'login':
if login.login(request.form):
# get username, password, remember from form
flash('Login erfolgreich!', 'login')
return redirect(url_for('index'))
else:
flash('Ungültiger Benutzername, Passwort oder Registrierung noch nicht bestätigt.', 'login')
# Render the main page with the current username
return render_template('index.html', page='index', user_name=session['username'])
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
if login.register(request):
flash('''
Du erhältst in den nächsten Minuten eine eMail mit einem Bestätigungslink.
Bitte klicke auf diesen Link, um deine Registrierung abzuschließen.
''', 'register')
return redirect(url_for('index'))
return render_template('index.html', page='register', user_name=session['username'])

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

View File

@ -0,0 +1,20 @@
function validateForm() {
var username = document.forms["loginForm"]["username"].value;
var password = document.forms["loginForm"]["password"].value;
if (username == "" || password == "") {
alert("Benutzername und Passwort müssen ausgefüllt werden.");
return false;
}
return true;
}
function checkPasswords() {
var password = document.forms["registerForm"]["password"].value;
var confirmPassword = document.forms["registerForm"]["password_repeat"].value;
if (password != confirmPassword) {
alert("Passwörter stimmen nicht überein.");
return false;
}
return true;
}

View File

@ -0,0 +1,103 @@
:root {
--primary-color: #102037; /* Definieren Sie die primäre Farbe */
--secondary-color: #f78b47; /* Definieren Sie die sekundäre Farbe */
--link-default-color: #ffffff; /* Definieren Sie die Link-Hover-Farbe */
--link-hover-color: #ffcc00; /* Definieren Sie die Link-Hover-Farbe */
--link-active-color: #ffcc00; /* Definieren Sie die Link-Hover-Farbe */
--background-color: #d4c4c4; /* Definieren Sie die Hintergrundfarbe */
--nav-background-color: #102037; /* Definieren Sie die Hintergrundfarbe */
--box-background-color: #102037;
}
body {
color: #ffffff;
background-color: var(--background-color);
}
.light {
color: #cdcdcd;
font-weight: 400;
font-size: small;
}
.sidebar {
height: 100%;
position: sticky;
top: 0;
background-color: var(--background-color);
}
.main-content {
background-color: var(--background-color);
}
.profile-card,
.story,
.post,
.who-to-follow,
.news {
background-color: var(--box-background-color);
padding: 20px;
border-radius: 15px;
margin-bottom: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}
.headbar {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}
.profile-card img,
.who-to-follow img {
width: 60px;
height: 60px;
object-fit: cover;
border-radius: 50%;
}
.story input {
border-radius: 30px;
}
.story button {
border-radius: 20px;
}
.post img {
width: 100%;
border-radius: 15px;
margin-top: 10px;
}
.who-to-follow button {
border-radius: 20px;
}
.navbar {
background-color: var(--nav-background-color);
padding: 0;
}
.navbar-nav .nav-link {
color: var(--link-default-color)
}
.navbar-nav .nav-link:hover {
color: var(--link-hover-color);
}
.navbar-nav .nav-link.active {
color: var(--link-active-color);
}
a {
color: #ffcc00;
}
a:hover {
color: #c07427;
}
.logo {
display:inline;
width: 50px;
margin: 0;
padding: 0;
}
.footer {
background-color: var(--nav-background-color);
padding: 0;
box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.3);
}
.errormsg {
color: red;
font-size: 15px;
}

View File

@ -0,0 +1,48 @@
<!-- Post a Story -->
<!--
<div class="story p-3">
<div class="d-flex align-items-center">
<img
src="https://via.placeholder.com/50"
class="rounded-circle me-3"
alt="Profile Picture" />
<input type="text" class="form-control" placeholder="Share your thoughts..." />
</div>
<div class="d-flex justify-content-around mt-3">
<button class="btn btn-outline-primary">Photo</button>
<button class="btn btn-outline-primary">Video</button>
<button class="btn btn-outline-primary">Event</button>
<button class="btn btn-outline-primary">Feeling/Activity</button>
</div>
</div>
-->
<!-- Posts -->
<div class="post p-3">
<div class="d-flex">
<img
src="../static/images/logo.png"
class="rounded-circle me-3"
style="width: 300px; height: 300px;"
alt="Profile Picture" />
<div class="my-3">
<h6>Lernplattform für <br>Rettungs- und Notfallsanitäter</h6>
<p class="light" style="text-align: justify;">
Willkommen auf unserer Lernplattform für Rettungssanitäter und Notfallsanitäter,
basierend auf dem bewährten Kartensystem nach Leitner.
Unsere Plattform bietet Dir die Möglichkeit,
Deine Kenntnisse und Fähigkeiten effektiv zu vertiefen und zu erweitern. <br><br>
Bei Interesse bist Du herzlich eingeladen, an der Entwicklung von Fragen und Aufgaben mitzuwirken.
Unsere Plattform ist und bleibt kostenlos, um alle Mitarbeiter im Rettungsdienst bestmöglich zu unterstützen.
</p>
</div>
</div>
<p class="mt-3">
I'm thrilled to share that I've completed a graduate certificate course in project
management with the president's honor roll.
</p>
<img src="https://via.placeholder.com/600x300" alt="Post Image" />
</div>

View File

@ -0,0 +1,39 @@
<div class="who-to-follow p-3">
<h6>Lernfelder</h6>
<div class="d-flex align-items-center my-2">
<img
src="https://via.placeholder.com/50"
class="rounded-circle me-3"
alt="Profile Picture" />
<div>
<h6 class="mb-0">Anatomie</h6>
<small class="light">RettSan</small>
</div>
<button class="btn btn-outline-primary ms-auto">+</button>
</div>
<div class="d-flex align-items-center my-2">
<img
src="https://via.placeholder.com/50"
class="rounded-circle me-3"
alt="Profile Picture" />
<div>
<h6 class="mb-0">Medikamente</h6>
<small class="light">NotSan</small>
</div>
<button class="btn btn-outline-primary ms-auto">+</button>
</div>
<div class="d-flex align-items-center my-2">
<img
src="https://via.placeholder.com/50"
class="rounded-circle me-3"
alt="Profile Picture" />
<div>
<h6 class="mb-0">Herzkreislauf</h6>
<small class="light">RettSan</small>
</div>
<button class="btn btn-outline-primary ms-auto">+</button>
</div>
<div class="text-center mt-3">
<button class="btn btn-link">Mehr Lernfelder</button>
</div>
</div>

View File

@ -0,0 +1,54 @@
<!-- wenn logged out -->
{% if not session['logged_in'] %}
<h5>{{ user_name }}</h5>
<p>Login oder <a href="/register">Registrieren</a></p>
<p class="light">Warum registrieren? Zum Schutz der Daten und dem Speichern deines Lernfortschrittes.</p>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
{% if category == 'login' %}
<p class="errormsg">{{message}}</p>
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
<form name="loginForm" action="/login" method="post" onsubmit="return validateForm()">
<div class="row mb-3">
<label for="inputEmail3" class="col-sm-3 col-form-label">Benutzer</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="username" name="username">
</div>
</div>
<div class="row mb-3">
<label for="inputPassword3" class="col-sm-3 col-form-label">Password</label>
<div class="col-sm-8">
<input type="password" class="form-control" id="password" name="password">
</div>
</div>
<div class="row mb-3">
<div class="col-sm-8 offset-2">
<input type="checkbox" name="remember" id="remember">
<label for="remember">Eingeloggt bleiben</label>
</div>
</div>
<input type="hidden" name="form_id" value="login">
<button type="submit" class="btn btn-primary">Einloggen</button>
</form>
{% endif %}
<!-- wenn logged out -->
<!-- wenn logged in -->
{% if session['logged_in'] %}
<!--<img src="https://via.placeholder.com/100" alt="Profile Picture" />-->
<h5>{{ user_name }}</h5>
<p>Web Developer at Webestica</p>
<p class="light">I'd love to change the world, but they wont give me the source code.</p>
<div class="d-flex justify-content-around">
<span>256 Posts</span>
<span>2.5K Followers</span>
<span>365 Following</span>
</div>
{% endif %}
<!-- wenn logged in -->

View File

@ -0,0 +1,28 @@
<div class="story p-3 shadow-sm">
<div>
<h5>Registrierung</h5>
<p>Registriere dich, um die Plattform zu nutzen. Deine Daten werden nicht an Dritte weitergegeben oder anderweitig anderweitig
verarbeitet. Die dienen lediglich zur Authentifizierung und Speicherung deines Lernfortschrittes.</p>
</div>
<form name="registerForm" method="post" onsubmit="return checkPasswords()">
<div>
<div class="row">
<div class="col py-3">
Benutzername: <input type="text" name="username" class="form-control" placeholder="Benutzername" tabindex="1" required />
<br>
Passwort: <input type="password" id="password" name="password" class="form-control" placeholder="Passwort" tabindex="3" required />
</div>
<div class="col py-3">
EMail: <input type="email" name="email" class="form-control" placeholder="EMail" tabindex="2" required />
<br>
Passwort wiederholen: <input type="password" id="password_repeat" name="password_repeat" class="form-control" tabindex="4" placeholder="Passwort wiederholen" required />
</div>
</div>
</div>
<div class="d-flex justify-content-around mt-3">
<button type="submit" class="btn btn-outline-primary">Registrieren</button>
</div>
</form>
</div>

View File

@ -0,0 +1,81 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lernplattform EMT/Paramedic</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="../static/style.css" rel="stylesheet"/>
<script src="../static/javascript.js"></script>
</head>
<body>
{% include 'nav.html' %}
<div class="container-fluid">
<div class="row">
<!-- Sidebar -->
<div class="col-12 col-md-3 sidebar mb-3">
<div class="profile-card text-center p-3">
{% include 'block_login.html' %}
</div>
<!--
<div class="list-group">
<a href="#" class="list-group-item list-group-item-action">Feed</a>
<a href="#" class="list-group-item list-group-item-action">Connections</a>
<a href="#" class="list-group-item list-group-item-action">Latest News</a>
<a href="#" class="list-group-item list-group-item-action">Events</a>
<a href="#" class="list-group-item list-group-item-action">Groups</a>
<a href="#" class="list-group-item list-group-item-action">Notifications</a>
<a href="#" class="list-group-item list-group-item-action">Settings</a>
</div>
-->
</div>
<!-- Main Content -->
<div class="col-12 col-md-6 main-content mb-3">
{% if not page or page == '' or page == 'index' %}
{% include 'block_content_index.html' %}
{% elif page == 'register' %}
{% include 'block_register.html' %}
{% endif %}
</div>
<!-- Right Sidebar -->
<div class="col-12 col-md-3 mb-3">
<!-- Who to Follow -->
{% include 'block_lernfelder.html' %}
<!-- Today's News -->
<div class="news p-3">
<h6>Datenbank - Inhalte</h6>
<ul class="list-unstyled">
<li class="mb-2">
Lernfelder <small class="light">3</small>
</li>
<li class="mb-2">
Fragen RettSan <small class="light">38</small>
</li>
<li class="mb-2">
Fragen NotSan <small class="light">40</small>
</li>
</ul>
</div>
</div>
</div>
</div>
<footer class="footer text-center py-3 mt-3">
<div class="container">
<small>© 2024 Manuel Weiser. Alle Rechte vorbehalten.</small>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,34 @@
<nav class="navbar navbar-expand-lg navbar-light shadow-sm mb-3">
<div class="container-fluid headbar">
<a class="navbar-brand" href="/"><img src="../static/images/logo.png" alt="EMT Paramedic Learn" class="logo" /></a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarNav"
aria-controls="navbarNav"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/">Start</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Lernfelder</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Account</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Impressum</a>
</li>
</ul>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Suche" aria-label="Suche" />
</form>
</div>
</div>
</nav>

View File

@ -1,7 +0,0 @@
from app import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(120), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)

3
readme.md Normal file
View File

@ -0,0 +1,3 @@
** App Starten **
python3 -m lernplattform.app

15
setup.py Normal file
View File

@ -0,0 +1,15 @@
from setuptools import setup, find_packages
VERSION = '0.0.1'
setup(
name='lernplattform',
version=VERSION,
license='MIT',
description='Eine Plattform zum lernen nach dem Leitner System',
author='Manuel Weiser',
author_email='manuel.weiser@me.com',
url='https://gitlab.fire-devils.org/ManuelW/Lerndatenbank',
packages=find_packages(exclude=('tests', 'docs', instance, env, _idee, __pycache__, templates)),
python_requires='>=3.10'
)

View File

@ -1,233 +0,0 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Social Media Layout</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<style>
.sidebar {
height: 100%;
position: sticky;
top: 0;
background-color: #f0f2f5;
}
.main-content {
background-color: #f0f2f5;
padding: 20px;
}
.profile-card,
.story,
.post,
.who-to-follow,
.news {
background-color: #ffffff;
padding: 20px;
border-radius: 15px;
margin-bottom: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.profile-card img,
.who-to-follow img {
width: 60px;
height: 60px;
object-fit: cover;
border-radius: 50%;
}
.story input {
border-radius: 30px;
}
.story button {
border-radius: 20px;
}
.post img {
width: 100%;
border-radius: 15px;
margin-top: 10px;
}
.who-to-follow button {
border-radius: 20px;
}
.navbar,
footer,
body {
background-color: #f0f2f5;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm mb-3">
<div class="container-fluid">
<a class="navbar-brand" href="#"><img src="https://via.placeholder.com/30" alt="Logo" /></a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarNav"
aria-controls="navbarNav"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Demo</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pages</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Account</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">My Network</a>
</li>
</ul>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search" />
</form>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<!-- Sidebar -->
<div class="col-12 col-md-3 sidebar mb-3">
<div class="profile-card text-center p-3">
<img src="https://via.placeholder.com/100" alt="Profile Picture" />
<h5>Sam Lanson</h5>
<p>Web Developer at Webestica</p>
<p class="text-muted">I'd love to change the world, but they wont give me the source code.</p>
<div class="d-flex justify-content-around">
<span>256 Posts</span>
<span>2.5K Followers</span>
<span>365 Following</span>
</div>
</div>
<div class="list-group">
<a href="#" class="list-group-item list-group-item-action">Feed</a>
<a href="#" class="list-group-item list-group-item-action">Connections</a>
<a href="#" class="list-group-item list-group-item-action">Latest News</a>
<a href="#" class="list-group-item list-group-item-action">Events</a>
<a href="#" class="list-group-item list-group-item-action">Groups</a>
<a href="#" class="list-group-item list-group-item-action">Notifications</a>
<a href="#" class="list-group-item list-group-item-action">Settings</a>
</div>
</div>
<!-- Main Content -->
<div class="col-12 col-md-6 main-content mb-3">
<!-- Post a Story -->
<div class="story p-3 shadow-sm">
<div class="d-flex align-items-center">
<img
src="https://via.placeholder.com/50"
class="rounded-circle me-3"
alt="Profile Picture" />
<input type="text" class="form-control" placeholder="Share your thoughts..." />
</div>
<div class="d-flex justify-content-around mt-3">
<button class="btn btn-outline-primary">Photo</button>
<button class="btn btn-outline-primary">Video</button>
<button class="btn btn-outline-primary">Event</button>
<button class="btn btn-outline-primary">Feeling/Activity</button>
</div>
</div>
<!-- Posts -->
<div class="post p-3 shadow-sm">
<div class="d-flex">
<img
src="https://via.placeholder.com/50"
class="rounded-circle me-3"
alt="Profile Picture" />
<div>
<h6>Lori Ferguson</h6>
<small class="text-muted">Web Developer at Webestica • 2hr</small>
</div>
</div>
<p class="mt-3">
I'm thrilled to share that I've completed a graduate certificate course in project
management with the president's honor roll.
</p>
<img src="https://via.placeholder.com/600x300" alt="Post Image" />
</div>
</div>
<!-- Right Sidebar -->
<div class="col-12 col-md-3 mb-3">
<!-- Who to Follow -->
<div class="who-to-follow p-3 shadow-sm">
<h6>Who to follow</h6>
<div class="d-flex align-items-center my-2">
<img
src="https://via.placeholder.com/50"
class="rounded-circle me-3"
alt="Profile Picture" />
<div>
<h6 class="mb-0">Judy Nguyen</h6>
<small class="text-muted">News anchor</small>
</div>
<button class="btn btn-outline-primary ms-auto">+</button>
</div>
<div class="d-flex align-items-center my-2">
<img
src="https://via.placeholder.com/50"
class="rounded-circle me-3"
alt="Profile Picture" />
<div>
<h6 class="mb-0">Amanda Reed</h6>
<small class="text-muted">Web Developer</small>
</div>
<button class="btn btn-outline-primary ms-auto">+</button>
</div>
<div class="d-flex align-items-center my-2">
<img
src="https://via.placeholder.com/50"
class="rounded-circle me-3"
alt="Profile Picture" />
<div>
<h6 class="mb-0">Billy Vasquez</h6>
<small class="text-muted">News anchor</small>
</div>
<button class="btn btn-outline-primary ms-auto">+</button>
</div>
<div class="text-center mt-3">
<button class="btn btn-link">View more</button>
</div>
</div>
<!-- Today's News -->
<div class="news p-3 shadow-sm">
<h6>Today's news</h6>
<ul class="list-unstyled">
<li class="mb-2">
Ten questions you should answer truthfully <small class="text-muted">2hr</small>
</li>
<li class="mb-2">
Five unbelievable facts about money <small class="text-muted">3hr</small>
</li>
<li class="mb-2">
Best Pinterest Boards for learning about business <small class="text-muted">4hr</small>
</li>
<li class="mb-2">
Skills that you can learn from ... <small class="text-muted">4hr</small>
</li>
</ul>
</div>
</div>
</div>
</div>
<footer class="bg-white text-center py-3 shadow-sm mt-3">
<div class="container">
<small>© 2024 Webestica. Alle Rechte vorbehalten.</small>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.min.js"></script>
</body>
</html>

View File

@ -1,30 +0,0 @@
from sqlalchemy import inspect, Integer, String
def check_and_create_tables(db):
inspector = inspect(db.engine)
# Überprüfen, ob die Tabelle 'user' existiert
if not inspector.has_table('user'):
print("Tabelle 'user' existiert nicht, sie wird erstellt.")
db.create_all()
else:
print("Tabelle 'user' existiert.")
# Überprüfen der Spalten
columns = inspector.get_columns('user')
column_names = [col['name'] for col in columns]
# Benötigte Spalten
required_columns = {
'id': Integer,
'username': String,
'email': String
}
for col_name, col_type in required_columns.items():
if col_name not in column_names:
print(f"Spalte '{col_name}' fehlt, sie wird hinzugefügt.")
with db.engine.connect() as conn:
if col_type == Integer:
conn.execute(f'ALTER TABLE user ADD COLUMN {col_name} INTEGER')
elif col_type == String:
conn.execute(f'ALTER TABLE user ADD COLUMN {col_name} STRING')