This is my first Question I make on this forum. I am so desperate to find a solution... Hope I can learn from you guys. I had a solution, but with posting the whole directorytree in the browserwindow and knowing the filename, which is not like I want it.
Now I found such code snippet and changed it a little bit. Its generator expression, which is I think not supported with Jinja2:
import os
path = r"C:/Users/add706/Documents/NRL_webseite/website/static/uploads"
def get_files(path):
for file in os.listdir(path):
if os.path.isfile(os.path.join(path, file)):
yield file
for file in get_files(path):
print(file)
The output gives me 3 files inside the path: 1.jpeg postgre.jpeg winrar-x64-610d.exe
I am trying to make a list and pass it to JINJA2. I have created already a template, but somehow, when I run flask, I cant list the files and the print function is empty. Since 3 days I am sitting on it and there is not even an error message, which could help me.
This is my original outtake of auth.py (imports of libraries are fine, not listed here):
path = r"C:/Users/add706/Documents/NRL_webseite/website/static/uploads"
@auth.route('/', methods = ['GET', 'POST'])
def get_files(path):
for file in os.listdir(path):
if os.path.isfile(os.path.join(path, file)):
return (os.listdir(path))
files=[]
for file in get_files(path):
files.append(file)
print(files)
return render_template('home.html', files=get_files(path))
This is my original outtake of home.html template (which was %extended%), looping through the returned files ( I wish to...):
<!-- download Folder-->
<div align="center">
<image src="{{ url_for('static', filename='uploads/postgre.jpeg')}}">
</ul>
{% for file in files %}
<li ><a href="#">{{ file }}</a></li>
{% endfor %}
</ul>
</div>
The question is now: What do I have to change in my both files that I can see the 3 files on my local webpage (http://127.0.0.1:5000/)? I would like to list them and make them clickable, so while clicking, the file can be downloaded as attachment. Second thing is, to list them with upload time. THird thing is, that the download process, let a window popping up, which asks me "DO you wish to download (filename). To visualize my problem, I uploaded an image and drew red boxes. Thanks in regard for every help out there.
Image link: (https://imgur.com/a/z4l8zH2)
I have found this article, which says in my script that tree is undefined (List files in directories with flask), so I gave it up.
CodePudding user response:
You can indeed use a generator inside jinja2.
The example I wrote should meet your needs.
It displays the files within the directory as a list. Each entry is assigned its size and the time of upload. The uploads folder is inside the instance folder to separate the files from the application.
I use flask-moment to show the correct times. This uses moment.js and displays the timestamp in the respective time zone of the client.
I use a custom Jinja2 filter to display the file size.
If a file is clicked to download, a dialog opens that requests confirmation. This is done using JavaScript.
Have fun achieving your goals.
Flask (app.py)
from flask import (
Flask,
render_template,
send_from_directory
)
from flask_moment import Moment
from datetime import datetime
import os
def byte_units(value, units=-1):
UNITS=('Bytes', 'KB', 'MB', 'GB', 'TB', 'EB', 'ZB', 'YB')
i=1
value /= 1000.0
while value > 1000 and (units == -1 or i < units) and i 1 < len(UNITS):
value /= 1000.0
i = 1
return f'{round(value,3):.3f} {UNITS[i]}'
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = os.path.join(app.instance_path, 'uploads')
app.jinja_env.filters.update(byte_units = byte_units)
moment = Moment(app)
try:
os.makedirs(app.config['UPLOAD_FOLDER'])
except:
pass
def get_files(target):
for file in os.listdir(target):
path = os.path.join(target, file)
if os.path.isfile(path):
yield (
file,
datetime.utcfromtimestamp(os.path.getmtime(path)),
os.path.getsize(path)
)
@app.route('/')
def index():
files = get_files(app.config['UPLOAD_FOLDER'])
return render_template('index.html', **locals())
@app.route('/download/<path:filename>')
def download(filename):
return send_from_directory(
app.config['UPLOAD_FOLDER'],
filename,
as_attachment=True
)
HTML (templates/index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Index</title>
{{ moment.include_moment() }}
</head>
<body>
<table style="width:40%; margin:auto; table-layout: fixed;">
{% for filename, mtime, size in files -%}
<tr>
<td><a href="{{ url_for('download', filename=filename) }}" download>{{ filename }}</a></td>
<td>{{ moment(mtime, local=False).format('DD.MM.YYYY HH:mm') }}</td>
<td style="text-align:right;">{{ size | byte_units }}</td>
</tr>
{% endfor -%}
</table>
<script type="text/javascript">
(() => {
const elems = document.querySelectorAll('a[href][download]');
elems.forEach(elem => {
elem.addEventListener('click', evt => {
const isDonwload = window.confirm('Would you like to download this file?');
if (!isDonwload) { evt.preventDefault(); }
});
});
})();
</script>
</body>
</html>
I've added my code to your project. It should work now.
You should work on structuring your project so that you can find your way around the code more easily. I cannot relieve you of this task in this context.
(website/init.py)
from flask import Flask
from flask_login import LoginManager
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
import os
DB_NAME = "database.db"
db = SQLAlchemy()
moment = Moment()
def byte_units(value, units=-1):
UNITS=('Bytes', 'KB', 'MB', 'GB', 'TB', 'EB', 'ZB', 'YB')
i=1
value /= 1000.0
while value > 1000 and (units == -1 or i < units) and i 1 < len(UNITS):
value /= 1000.0
i = 1
return f'{round(value,3):.3f} {UNITS[i]}'
def create_app():
app = Flask(__name__)
app.config.from_mapping(
SECRET_KEY=b'your secret here',
SQLALCHEMY_DATABASE_URI='sqlite:///' os.path.join(app.instance_path, DB_NAME),
SQLALCHEMY_TRACK_MODIFICATIONS=False,
UPLOAD_FOLDER=os.path.join(app.instance_path, 'uploads')
)
app.jinja_env.filters.update(byte_units = byte_units)
try:
os.makedirs(app.config['UPLOAD_FOLDER'])
except:
pass
db.init_app(app)
moment.init_app(app)
from .models import User, Note
create_database(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
@login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
from .views import views
from .auth import auth
app.register_blueprint(auth, url_prefix='/')
app.register_blueprint(views, url_prefix='/')
return app
def create_database(app):
if not os.path.exists(os.path.join(app.instance_path, DB_NAME)):
db.create_all(app=app)
print('Created Database!')
(website/auth.py)
import os
import json
from . import db
from .models import User
from flask import (
Blueprint,
flash,
redirect,
render_template,
request,
url_for
)
from flask_login import login_user, login_required, logout_user, current_user
auth = Blueprint('auth', __name__)
@auth.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form.get('email')
password = request.form.get('password')
user = User.query.filter_by(email=email).first()
if user:
if check_password_hash(user.password, password):
flash('Logged in successfully!', category='success')
login_user(user, remember=True)
return redirect(url_for('views.home'))
else:
flash('Incorrect password, try again.', category='error')
else:
flash('Email does not exist.', category='error')
return render_template('login.html', user=current_user)
@auth.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('auth.login'))
@auth.route('/sign-up', methods=['GET', 'POST'])
def sign_up():
if request.method == 'POST':
email = request.form.get('email')
first_name = request.form.get('firstName')
password1 = request.form.get('password1')
password2 = request.form.get('password2')
user = User.query.filter_by(email=email).first()
if user:
flash('Email already exists.', category='error')
elif len(email) < 4:
flash('Email must be greater than 3 characters.', category='error')
elif len(first_name) < 2:
flash('First name must be greater than 1 character.', category='error')
elif password1 != password2:
flash('Passwords don\'t match.', category='error')
elif len(password1) < 7:
flash('Password must be at least 7 characters.', category='error')
else:
new_user = User(email=email, first_name=first_name, password=generate_password_hash(
password1, method='sha256'))
db.session.add(new_user)
db.session.commit()
login_user(new_user, remember=True)
flash('Account created!', category='success')
return redirect(url_for('views.home'))
return render_template('sign_up.html', user=current_user)
(website/views.py)
from . import db
from .models import Note
from flask import Blueprint, current_app, flash, jsonify, render_template, request
from flask_login import login_required, current_user
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
import os
views = Blueprint('views', __name__)
@views.route('/', methods=['GET', 'POST'])
@login_required
def home():
if request.method == 'POST':
note = request.form.get('note')
if len(note) < 1:
flash('Note is too short!', category='error')
else:
new_note = Note(data=note, user_id=current_user.id)
db.session.add(new_note)
db.session.commit()
flash('Note added!', category='success')
user=current_user
files = get_files(current_app.config['UPLOAD_FOLDER'])
return render_template('home.html', **locals())
@views.route('/delete-note', methods=['POST'])
def delete_note():
note = json.loads(request.data)
noteId = note['noteId']
note = Note.query.get(noteId)
if note:
if note.user_id == current_user.id:
db.session.delete(note)
db.session.commit()
return jsonify({})
# ---
@views.route('/about')
def about():
return render_template('about.html', user=None)
# ---
@views.route('/upload', methods = ['GET', 'POST'])
def uploadfile():
upload_folder = current_app.config['UPLOAD_FOLDER']
if request.method == 'POST': # check if the method is post
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file'] # get the file from the files object
if file.filename == '':
flash('No selected file')
return redirect(request.url)
file.save(os.path.join(
upload_folder ,
secure_filename(file.filename))) # this will secure the file
flash('file uploaded successfully') # Display this message after uploading
return redirect('/')
def get_files(target):
for file in os.listdir(target):
path = os.path.join(target, file)
if os.path.isfile(path):
yield (
file,
datetime.utcfromtimestamp(os.path.getmtime(path)),
os.path.getsize(path)
)
@views.route('/download/<path:filename>')
def download(filename):
return send_from_directory(
app.config['UPLOAD_FOLDER'],
filename,
as_attachment=True
)
(templates/base.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3 Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
crossorigin="anonymous"
/>
<title>{% block title %}Home{% endblock %}</title>
{{ moment.include_moment() }}
</head>
<body>
<nav >
<button
type="button"
data-toggle="collapse"
data-target="#navbar"
>
<span ></span>
</button>
<div id="navbar">
<div >
{% if user.is_authenticated %}
<a id="home" href="/">Home</a>
<a id="logout" href="/logout">Logout</a>
{% else %}
<a id="login" href="/login">Login</a>
<a id="signUp" href="/sign-up">Sign Up</a>
<a id="Über Uns" href="/about">Über uns</a>
{% endif %}
</div>
</div>
</nav>
{% with messages = get_flashed_messages(with_categories=true) %} {% if
messages %} {% for category, message in messages %} {% if category ==
'error' %}
<div role="alert">
{{ message }}
<button type="button" data-dismiss="alert">
<span aria-hidden="true">×</span>
</button>
</div>
{% else %}
<div role="alert">
{{ message }}
<button type="button" data-dismiss="alert">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %} {% endfor %} {% endif %} {% endwith %}
<div >{% block content %} {% endblock %}</div>
<script
src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"
></script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5 76PVCmYl"
crossorigin="anonymous"
></script>
<script
type="text/javascript"
src="{{ url_for('static', filename='index.js') }}"
></script>
</body>
</html>
(templates/home.html)
{% extends "base.html" -%}
{% block title %}Home{% endblock -%}
{% block content -%}
<h1 align="center">Notes</h1>
<ul id="notes">
{% for note in user.notes %}
<li >
{{ note.data }}
<button type="button" onClick="deleteNote({{ note.id }})">
<span aria-hidden="true">×</span>
</button>
</li>
{% endfor %}
</ul>
<form method="POST">
<textarea name="note" id="note" ></textarea>
<br />
<div align="center">
<button type="submit" >Add Note</button>
</div>
</form>
<br>
<br>
<br>
<br>
<!-- upload Folder-->
<div >
<div >
<div >
<h1 align="center">Datei Upload</h1>
<hr>
<form
action="http://localhost:5000/upload"
method="POST"
enctype="multipart/form-data">
<input type="file" name="file" />
<button type="submit" >Upload</button>
</form>
</div>
</div>
</div>
<br>
<br>
<br>
<br>
<!-- download Folder-->
<div align="center">
<image src="{{ url_for('static', filename='uploads/postgre.jpeg')}}">
</div>
<table style="width:40%; margin:auto; table-layout: fixed;">
{% for filename, mtime, size in files -%}
<tr>
<td><a href="{{ url_for('views.download', filename=filename) }}" download>{{ filename }}</a></td>
<td>{{ moment(mtime, local=False).format('DD.MM.YYYY HH:mm') }}</td>
<td style="text-align:right;">{{ size | byte_units }}</td>
</tr>
{% endfor -%}
</table>
<script type="text/javascript">
(() => {
const elems = document.querySelectorAll('a[href][download]');
elems.forEach(elem => {
elem.addEventListener('click', evt => {
const isDonwload = window.confirm('Would you like to download this file?');
if (!isDonwload) { evt.preventDefault(); }
});
});
})();
</script>
{% endblock -%}
CodePudding user response:
With the help of @ Detlef a local webserver was created, which allows you to log in, sign up and leave notes. Then there were an upload and a download option set up.
I begin with the tree structure.
C:.
| main.py
| output.doc
|
---instance
| | database.db
| |
| \---uploads
| postgre.jpeg
| project.jpg
|
---website
| | auth.py
| | database.db
| | models.py
| | output.doc
| | views.py
| | __init__.py
| |
| ---static
| | | index.js
| | |
| | \---Bilder
| | sun.jpg
| | logo.png
| | postgre.jpeg
| |
| ---templates
| | about.html
| | base.html
| | home.html
| | login.html
| | sign_up.html
| |
| \---__pycache__
| app.cpython-39.pyc
| auth.cpython-39.pyc
| download.cpython-39.pyc
| models.cpython-39.pyc
| views.cpython-39.pyc
| __init__.cpython-39.pyc
|
Starting with the main.py:
from website import create_app # website folder
app = create_app()
if __name__ == '__main__':
app.run(debug=True)
This is the auth.py:
from . import db
from werkzeug.security import generate_password_hash, check_password_hash
from .models import User
from flask import (
Blueprint,
flash,
redirect,
render_template,
request,
url_for
)
from flask_login import login_user, login_required, logout_user, current_user
auth = Blueprint('auth', __name__)
@auth.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form.get('email')
password = request.form.get('password')
user = User.query.filter_by(email=email).first()
if user:
if check_password_hash(user.password, password):
flash('Logged in successfully!', category='success')
login_user(user, remember=True)
return redirect(url_for('views.home'))
else:
flash('Incorrect password, try again.', category='error')
else:
flash('Email does not exist.', category='error')
return render_template('login.html', user=current_user)
@auth.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('auth.login'))
@auth.route('/sign-up', methods=['GET', 'POST'])
def sign_up():
if request.method == 'POST':
email = request.form.get('email')
first_name = request.form.get('firstName')
password1 = request.form.get('password1')
password2 = request.form.get('password2')
user = User.query.filter_by(email=email).first()
if user:
flash('Email already exists.', category='error')
elif len(email) < 4:
flash('Email must be greater than 3 characters.', category='error')
elif len(first_name) < 2:
flash('First name must be greater than 1 character.', category='error')
elif password1 != password2:
flash('Passwords don\'t match.', category='error')
elif len(password1) < 7:
flash('Password must be at least 7 characters.', category='error')
else:
new_user = User(email=email, first_name=first_name, password=generate_password_hash(
password1, method='sha256'))
db.session.add(new_user)
db.session.commit()
login_user(new_user, remember=True)
flash('Account created!', category='success')
return redirect(url_for('views.home'))
return render_template('sign_up.html', user=current_user)
This is the views.py:
from . import db
from .models import Note
from flask import Blueprint, render_template, request, flash, redirect, url_for, send_from_directory, abort, jsonify
from flask_login import login_required, current_user
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
import os
import json
from flask_moment import Moment
from flask import Flask
views = Blueprint('views', __name__)
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = os.path.join(app.instance_path, '/uploads')
moment = Moment(app)
@views.route('/', methods=['GET', 'POST'])
@login_required
def home():
if request.method == 'POST':
note = request.form.get('note')
if len(note) < 1:
flash('Note is too short!', category='error')
else:
new_note = Note(data=note, user_id=current_user.id)
db.session.add(new_note)
db.session.commit()
flash('Note added!', category='success')
user=current_user
files = get_files(app.config['UPLOAD_FOLDER'])
return render_template('home.html', **locals())
@views.route('/delete-note', methods=['POST'])
def delete_note():
note = json.loads(request.data)
noteId = note['noteId']
note = Note.query.get(noteId)
if note:
if note.user_id == current_user.id:
db.session.delete(note)
db.session.commit()
return jsonify({})
# ---
@views.route('/about')
def about():
return render_template('about.html', user=None)
# ---
@views.route('/upload', methods = ['GET', 'POST'])
def uploadfile():
upload_folder = app.config['UPLOAD_FOLDER']
if request.method == 'POST': # check if the method is post
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file'] # get the file from the files object
if file.filename == '':
flash('No selected file')
return redirect(request.url)
file.save(os.path.join(
upload_folder ,
secure_filename(file.filename))) # this will secure the file
flash('file uploaded successfully') # Display this message after uploading
return redirect('/')
def get_files(target):
for file in os.listdir(target):
path = os.path.join(target, file)
if os.path.isfile(path):
yield (
file,
datetime.utcfromtimestamp(os.path.getmtime(path)),
os.path.getsize(path)
)
@views.route('/download/<path:filename>')
def download(filename):
return send_from_directory(
app.config['UPLOAD_FOLDER'],
filename,
as_attachment=True
)
This is the init.py:
from flask import Flask
from flask_login import LoginManager
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
import os
DB_NAME = "database.db"
db = SQLAlchemy()
moment = Moment()
def byte_units(value, units=-1):
UNITS=('Bytes', 'KB', 'MB', 'GB', 'TB', 'EB', 'ZB', 'YB')
i=1
value /= 1000.0
while value > 1000 and (units == -1 or i < units) and i 1 < len(UNITS):
value /= 1000.0
i = 1
return f'{round(value,3):.3f} {UNITS[i]}'
def create_app():
app = Flask(__name__)
app.config.from_mapping(
SECRET_KEY=b'your secret here',
SQLALCHEMY_DATABASE_URI='sqlite:///' os.path.join(app.instance_path, DB_NAME),
SQLALCHEMY_TRACK_MODIFICATIONS=False,
UPLOAD_FOLDER=os.path.join(app.instance_path, 'uploads')
)
app.jinja_env.filters.update(byte_units = byte_units)
try:
os.makedirs(app.config['UPLOAD_FOLDER'])
except:
pass
db.init_app(app)
moment.init_app(app)
from .models import User, Note
create_database(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
@login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
from .views import views
from .auth import auth
app.register_blueprint(auth, url_prefix='/')
app.register_blueprint(views, url_prefix='/')
return app
def create_database(app):
if not os.path.exists(os.path.join(app.instance_path, DB_NAME)):
db.create_all(app=app)
print('Created Database!')
This is the models.py:
from . import db
from flask_login import UserMixin
from sqlalchemy.sql import func
class Note(db.Model):
id = db.Column(db.Integer, primary_key=True)
data = db.Column(db.String(10000))
date = db.Column(db.DateTime(timezone=True), default=func.now())
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150), unique=True)
password = db.Column(db.String(150))
first_name = db.Column(db.String(150))
notes = db.relationship('Note')
THis is the home.html template:
{% extends "base.html" -%}
{% block title %}Home{% endblock -%}
{% block content -%}
<h1 align="center">Notes</h1>
<ul id="notes">
{% for note in user.notes %}
<li >
{{ note.data }}
<button type="button" onClick="deleteNote({{ note.id }})">
<span aria-hidden="true">×</span>
</button>
</li>
{% endfor %}
</ul>
<form method="POST">
<textarea name="note" id="note" ></textarea>
<br />
<div align="center">
<button type="submit" >Add Note</button>
</div>
</form>
<br>
<br>
<br>
<br>
<!-- upload Folder-->
<div >
<div >
<div >
<h1 align="center">Datei Upload</h1>
<hr>
<form
action="http://localhost:5000/upload"
method="POST"
enctype="multipart/form-data">
<input type="file" name="file" />
<button type="submit" >Upload</button>
</form>
</div>
</div>
</div>
<br>
<br>
<br>
<br>
<!-- download Folder-->
<div align="center">
<image src="{{ url_for('static', filename='Bilder/postgre.jpeg')}}">
</div>
<head>
<style>
table, th, td {
border: 1px solid black;
}
</style>
</head>
<body>
<h1>Downloads</h1>
<table style="width:100%; margin:auto; table-layout: fixed;">
{% for filename, mtime, size in files -%}
<tr>
<th>Dateiname</th>
<th>Datum und Uhrzeit</th>
<th>Dateigröße</th>
</tr>
<tr>
<td><a href="{{ url_for('views.download', filename=filename) }}" download>{{ filename }}</a></td>
<td>{{ moment(mtime, local=False).format('DD.MM.YYYY HH:mm') }}</td>
<td style="text-align:right;">{{ size | byte_units }}</td>
</tr>
{% endfor -%}
</table>
<script type="text/javascript">
(() => {
const elems = document.querySelectorAll('a[href][download]');
elems.forEach(elem => {
elem.addEventListener('click', evt => {
const isDonwload = window.confirm('Möchten Sie die ausgewählte Datei herunterladen??');
if (!isDonwload) { evt.preventDefault(); }
});
});
})();
</script>
{% endblock -%}
This is the login.hmtl
{% extends "base.html" %} {% block title %}Login{% endblock %} {% block content
%}
<form method="POST">
<h3 align="center">Login</h3>
<div >
<label for="email">Email Addresse</label>
<input
type="email"
id="email"
name="email"
placeholder="Email Eingabe"
/>
</div>
<div >
<label for="password">Passwort</label>
<input
type="password"
id="password"
name="password"
placeholder="Passwort Eingabe"
/>
</div>
<br />
<button type="submit" >Login</button>
</form>
{% endblock %}
This is the sign_up.hmtl
{% extends "base.html" %} {% block title %}Sign Up{% endblock %} {% block
content %}
<body>
<h3 align="center"><img src="{{ url_for('static', filename='Bilder/Logo-NRL-blau.png') }}" alt=""></h3>
</body>
<form method="POST">
<h3 align="center">Sign Up</h3>
<div >
<label for="email">Email-Addresse</label>
<input
type="email"
id="email"
name="email"
placeholder="Email Eingabe"
/>
</div>
<div >
<label for="firstName">Vollständiger Name</label>
<input
type="text"
id="firstName"
name="firstName"
placeholder="Eingabe des vollständigen Namens"
/>
</div>
<div >
<label for="password1">Passwort</label>
<input
type="password"
id="password1"
name="password1"
placeholder="Passwort Eingabe"
/>
</div>
<div >
<label for="password2">Passwort (Wiederholung)</label>
<input
type="password"
id="password2"
name="password2"
placeholder="Passwort (Bestätigung)"
/>
</div>
<br />
<button type="submit" >Submit</button>
</form>
{% endblock %}
This is the base.hmtl
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3 Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
crossorigin="anonymous"
/>
<title>{% block title %}Home{% endblock %}</title>
{{ moment.include_moment() }}
</head>
<body>
<nav >
<button
type="button"
data-toggle="collapse"
data-target="#navbar"
>
<span ></span>
</button>
<div id="navbar">
<div >
{% if user.is_authenticated %}
<a id="home" href="/">Home</a>
<a id="logout" href="/logout">Logout</a>
{% else %}
<a id="login" href="/login">Login</a>
<a id="signUp" href="/sign-up">Sign Up</a>
<a id="Über Uns" href="/about">Über uns</a>
{% endif %}
</div>
</div>
</nav>
{% with messages = get_flashed_messages(with_categories=true) %} {% if
messages %} {% for category, message in messages %} {% if category ==
'error' %}
<div role="alert">
{{ message }}
<button type="button" data-dismiss="alert">
<span aria-hidden="true">×</span>
</button>
</div>
{% else %}
<div role="alert">
{{ message }}
<button type="button" data-dismiss="alert">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %} {% endfor %} {% endif %} {% endwith %}
<div >{% block content %} {% endblock %}</div>
<script
src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"
></script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5 76PVCmYl"
crossorigin="anonymous"
></script>
<script
type="text/javascript"
src="{{ url_for('static', filename='index.js') }}"
></script>
</body>
</html>
Have fun with it. AND THANKS to @ Detlef !!!!!!!