From ba22b3a03d229ecd89f7f24ca7ef8c08b410737f Mon Sep 17 00:00:00 2001 From: Kostanjevec Date: Fri, 13 May 2022 18:23:15 +0200 Subject: [PATCH] dodal vsebino po flask tutorialu... --- app/__init__.py | 13 ++++- app/app.py | 2 - app/auth.py | 95 ++++++++++++++++++++++++++++++ app/db.py | 57 ++++++++++++++++++ app/static/style.css | 134 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 297 insertions(+), 4 deletions(-) create mode 100644 app/db.py diff --git a/app/__init__.py b/app/__init__.py index 10f8976..cd9f1aa 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -9,7 +9,7 @@ def create_app(test_config=None): app.config.from_mapping( SECRET_KEY='dev', DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'), - ) + ) # = kaj naj tu piše? if test_config is None: # load the instance config, if it exists, when not testing @@ -29,4 +29,13 @@ def create_app(test_config=None): def hello(): return 'Hello, Woooorld!' - return app \ No newline at end of file + from . import db + db.init_app(app) + + from . import auth + app.register_blueprint(auth.bp) + + return app + + +app = create_app() \ No newline at end of file diff --git a/app/app.py b/app/app.py index 5de8b6e..1256e0a 100644 --- a/app/app.py +++ b/app/app.py @@ -1,5 +1,4 @@ #!/usr/bin/python3 -"""" from flask import Flask @@ -8,7 +7,6 @@ app = Flask(__name__) @app.route("/") def hello_world(): return "

Hello, World!

" -""" """ diff --git a/app/auth.py b/app/auth.py index e69de29..86dff1b 100644 --- a/app/auth.py +++ b/app/auth.py @@ -0,0 +1,95 @@ +import functools + +from flask import ( + Blueprint, flash, g, redirect, render_template, request, session, url_for +) +from werkzeug.security import check_password_hash, generate_password_hash + +# from db import get_db error + +bp = Blueprint('auth', __name__, url_prefix='/auth') + + +@bp.route('/register', methods=('GET', 'POST')) +def register(): + if request.method == 'POST': + username = request.form['username'] + password = request.form['password'] + db = get_db() + error = None + + if not username: + error = 'Username is required.' + elif not password: + error = 'Password is required.' + + if error is None: + try: + db.execute( + "INSERT INTO user (username, password) VALUES (?, ?)", + (username, generate_password_hash(password)), + ) + db.commit() + except db.IntegrityError: + error = f"User {username} is already registered." + else: + return redirect(url_for("auth.login")) + + flash(error) + + return render_template('auth/register.html') + + +@bp.route('/login', methods=('GET', 'POST')) +def login(): + if request.method == 'POST': + username = request.form['username'] + password = request.form['password'] + db = get_db() + error = None + user = db.execute( + 'SELECT * FROM user WHERE username = ?', (username,) + ).fetchone() + + if user is None: + error = 'Incorrect username.' + elif not check_password_hash(user['password'], password): + error = 'Incorrect password.' + + if error is None: + session.clear() + session['user_id'] = user['id'] + return redirect(url_for('index')) + + flash(error) + + return render_template('auth/login.html') + + +@bp.before_app_request +def load_logged_in_user(): + user_id = session.get('user_id') + + if user_id is None: + g.user = None + else: + g.user = get_db().execute( + 'SELECT * FROM user WHERE id = ?', (user_id,) + ).fetchone() + + +@bp.route('/logout') +def logout(): + session.clear() + return redirect(url_for('index')) + + +def login_required(view): + @functools.wraps(view) + def wrapped_view(**kwargs): + if g.user is None: + return redirect(url_for('auth.login')) + + return view(**kwargs) + + return wrapped_view \ No newline at end of file diff --git a/app/db.py b/app/db.py new file mode 100644 index 0000000..d07f501 --- /dev/null +++ b/app/db.py @@ -0,0 +1,57 @@ +import sqlite3 ## tu rabim nekaj drugega + +import click +from flask import current_app, g +from flask.cli import with_appcontext + + +def get_db(): + if 'db' not in g: + g.db = sqlite3.connect( + current_app.config['DATABASE'], + detect_types=sqlite3.PARSE_DECLTYPES + ) + g.db.row_factory = sqlite3.Row + + return g.db + + +def close_db(e=None): + db = g.pop('db', None) + + if db is not None: + db.close() + + +""" +open_resource() opens a file relative to the flaskr package, which is useful since you won’t necessarily know where that location is when deploying the application later. get_db returns a database connection, which is used to execute the commands read from the file. + +click.command() defines a command line command called init-db that calls the init_db function and shows a success message to the user. You can read Command Line Interface to learn more about writing commands. +""" + + +def init_db(): + db = get_db() + + with current_app.open_resource('schema.sql') as f: + db.executescript(f.read().decode('utf8')) + + +@click.command('init-db') +@with_appcontext +def init_db_command(): + """Clear the existing data and create new tables.""" + init_db() + click.echo('Initialized the database.') + +def init_app(app): + app.teardown_appcontext(close_db) + app.cli.add_command(init_db_command) + + +""" +app.teardown_appcontext() tells Flask to call that function when cleaning up after returning the response. + +app.cli.add_command() adds a new command that can be called with the flask command. +""" + diff --git a/app/static/style.css b/app/static/style.css index e69de29..6e2a6cd 100644 --- a/app/static/style.css +++ b/app/static/style.css @@ -0,0 +1,134 @@ +html { + font-family: sans-serif; + background: #eee; + padding: 1rem; + } + + body { + max-width: 960px; + margin: 0 auto; + background: white; + } + + h1, h2, h3, h4, h5, h6 { + font-family: serif; + color: #377ba8; + margin: 1rem 0; + } + + a { + color: #377ba8; + } + + hr { + border: none; + border-top: 1px solid lightgray; + } + + nav { + background: lightgray; + display: flex; + align-items: center; + padding: 0 0.5rem; + } + + nav h1 { + flex: auto; + margin: 0; + } + + nav h1 a { + text-decoration: none; + padding: 0.25rem 0.5rem; + } + + nav ul { + display: flex; + list-style: none; + margin: 0; + padding: 0; + } + + nav ul li a, nav ul li span, header .action { + display: block; + padding: 0.5rem; + } + + .content { + padding: 0 1rem 1rem; + } + + .content > header { + border-bottom: 1px solid lightgray; + display: flex; + align-items: flex-end; + } + + .content > header h1 { + flex: auto; + margin: 1rem 0 0.25rem 0; + } + + .flash { + margin: 1em 0; + padding: 1em; + background: #cae6f6; + border: 1px solid #377ba8; + } + + .post > header { + display: flex; + align-items: flex-end; + font-size: 0.85em; + } + + .post > header > div:first-of-type { + flex: auto; + } + + .post > header h1 { + font-size: 1.5em; + margin-bottom: 0; + } + + .post .about { + color: slategray; + font-style: italic; + } + + .post .body { + white-space: pre-line; + } + + .content:last-child { + margin-bottom: 0; + } + + .content form { + margin: 1em 0; + display: flex; + flex-direction: column; + } + + .content label { + font-weight: bold; + margin-bottom: 0.5em; + } + + .content input, .content textarea { + margin-bottom: 1em; + } + + .content textarea { + min-height: 12em; + resize: vertical; + } + + input.danger { + color: #cc2f2e; + } + + input[type=submit] { + align-self: start; + min-width: 10em; + } \ No newline at end of file