Git и Flask

Отчёт по установке Github-репозитория CyberPolygon-front и создания базового проекта на Flask

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