Git и Flask
Categories:
241-329 Пашковский
Отчёт по установке Github-репозитория CyberPolygon-front и создания базового проекта на Flask
GitHub – это облачная платформа для хостинга и разработки программного обеспечения. На ней можно хранить проекты в репозиториях, управлять версиями кода и работать вместе с другими программистами. Git – распределённая система управления версиями
Часть 1. Базовая работа с Git:
Установка git:
Скачиваем установщик git для Wind ows с официального сайта и устанавливаем его:
Рисунок 1
Проверяем установку:
Рисунок 2
Git успешно установлен
Опционально, но более чем желательно зайти в собственный Github профиль при помощи RSA ключа
Скачивание и настройка репозитория:
Рисунок 3 - скачивание репозитория
Следуем инструкциям по установке всех зависимостей:
Рисунок 4 - инструкции по установке проекта cyberpolygon-front
Устанавливаем NodeJS с официального сайта:
Рисунок 5 - официальный сайт NodeJS
Рисунок 6 - установка зависимостей проекта
У меня не удалось запустить проект нативно, поэтому я собрал и запустил контейнер, прилагаемый к проекту:
Рисунок 7 - запуск контейнера
Рисунок 8 - успешная работа сайта с локального хоста
Часть 2: проект на Flask
Создание проекта на Flask
Создаём директорию, виртуальное окружение и активируем его:
Рисунок 9 - настройка рабочей директории проекта Flask
Рисунок 10 - установка (на этом скриншоте - проверка) всех зависимостей
Напишем базовый код:
import os
from flask import Flask
def create_app(test_config=None):
*# create and configure the app*
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE='localhost:./database/flaskr.fdb',
USER='sysdba',
PASSWORD='masterkey'
)
if test_config is None:
app.config.from_pyfile('config.py', silent=True)
else:
app.config.from_mapping(test_config)
try:
os.makedirs(app.instance_path)
except OSError:
pass
def hello():
return 'Hello, World!'
return app
Рисунок 11 - результат работы базового кода в __init__.py
Добавим поддержку базы данных, используя следующий код:
import fdb
import click
from flask import current_app, g
from flask.cli import with_appcontext
def init_db():
try:
conn = fdb.connect(
dsn=current_app.config['DATABASE'],
user=current_app.config['USER'],
password=current_app.config['PASSWORD'],
fb_library_name=current_app.config['LIBRARY']
)
conn.drop_database()
except Exception as e:
print(e)
conn = fdb.create_database(
dsn=current_app.config['DATABASE'],
user=current_app.config['USER'],
password=current_app.config['PASSWORD'],
fb_library_name=current_app.config['LIBRARY']
)
metadata = [
'''
RECREATE TABLE users (
id integer generated by default as identity primary key,
username varchar(256) UNIQUE NOT NULL,
password varchar(256) NOT NULL
)
''',
'''
RECREATE TABLE posts (
id integer generated by default as identity primary key,
author_id INTEGER NOT NULL REFERENCES users (id),
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
title varchar(120) NOT NULL,
body varchar(5000) NOT NULL
)
'''
]
cursor = conn.cursor()
for query in metadata:
cursor.execute(query)
conn.commit()
def get_db():
if 'db' not in g:
g.db = fdb.connect(
dsn=current_app.config['DATABASE'],
user=current_app.config['USER'],
password=current_app.config['PASSWORD'],
fb_library_name=current_app.config['LIBRARY']
)
return g.db
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db.close()
@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)
Меняем код в __init__.py, добавляя одну строку в функцию
create_app:
Добавляем следующую строчку в функцию create_app
db.init_app(app)
Инициализируем базу данных с именем test:
Рисунок 12 - инициализация базы данных
Рисунок 13 - результат создания базы данных
Создание эскиза
Сделаем модуль аутентификации auth.py:
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 flaskr.db import get_db
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.cursor().execute(
"INSERT INTO users (username, password) VALUES (?,
?)",
(username, generate_password_hash(password)),
)
db.commit()
except db.DatabaseError as e:
if e.args[2] == 335544665:
*#isc_unique_key_violation*
error = f"User {username} is already registered."
else:
return redirect(url_for("auth.login"))
flash(error)
return render_template('auth/register.html')
Итоговый код auth.py:
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 flaskr.db import get_db
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.cursor().execute(
"INSERT INTO users (username, password) VALUES (?,
?)",
(username, generate_password_hash(password)),
)
db.commit()
except db.DatabaseError as e:
if e.args[2] == 335544665:
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.cursor().execute('SELECT * FROM users WHERE username
= ?', (username,) ).fetchonemap()
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.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
Создадим шаблоны:
base.html:
<!doctype html>
<title>{% block title %}{% endblock %} - Flaskr</title>
<link rel="stylesheet" href="{{ url_for('static',
filename='style.css') }}">
<nav>
<h1>Flaskr</h1>
<ul>
{% if g.user %}
<li><span>{{ g.user['username'] }}</span>
<li><a href="{{ url_for('auth.logout') }}">Log Out</a>
{% else %}
<li><a href="{{ url_for('auth.register') }}">Register</a>
<li><a href="{{ url_for('auth.login') }}">Log In</a>
{% endif %}
</ul>
</nav>
<section class="content">
<header>
{% block header %}{% endblock %}
</header>
{% for message in get_flashed_messages() %}
<div class="flash">{{ message }}</div>
{% endfor %}
{% block content %}{% endblock %}
</section>
register.html
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Register{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post">
<label for="username">Username</label>
<input name="username" id="username" required>
<label for="password">Password</label>
<input type="password" name="password" id="password"
required>
<input type="submit" value="Register">
</form>
{% endblock %}
login.html:
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Log In{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post">
<label for="username">Username</label>
<input name="username" id="username" required>
<label for="password">Password</label>
<input type="password" name="password" id="password"
required>
<input type="submit" value="Log In">
</form>
{% endblock %}
Получим результат:
Рисунок 14 - реализован вход в наше приложение
Вывод:
Скачан, собран и запущен репозиторий cyberpolygon-front, сделан простая форма входа и регистрации пользователя на Flask