1
0
Fork 0
mirror of https://github.com/EDeev/web-dev.git synced 2026-10-07 20:49:38 +03:00

Compare commits

..

4 commits

Author SHA1 Message Date
9a23fc52e0 README на русском и английском, скриншот экзамена
Отдельный ex/README.md со ссылкой на сайт и тестовыми аккаунтами объединён с общим README.
2026-10-02 21:29:26 +00:00
bc087c9e7c CI: синтаксис (ruff), тесты домашних заданий, импорт всех лабораторных и экзамена 2026-10-02 21:29:26 +00:00
69ced80d88 Режим отладки и SECRET_KEY из окружения, зависимости lab-4/5 закреплены
- app.run(debug=True) во всех лабораторных и экзамене заменён на FLASK_DEBUG=1 из
  окружения: отладчик Werkzeug позволяет выполнять код на сервере;
- secret_key — из SECRET_KEY, прежние значения остались только как запасные;
- lab-4/5: Flask-SQLAlchemy 2.5 + SQLAlchemy 1.4 (со свежим SQLAlchemy 2 не импортировались);
- неиспользуемые импорты и переменные удалены (ruff).
2026-10-02 21:27:00 +00:00
950154e23d Базы SQLite и загруженные картинки убраны из git
ex/db/library.db, ex/library.db, instance/*.db лабораторных, загрузки экзамена и lab-6 —
это данные, которые приложения создают сами (db_seed.py, create_all); папки для загрузок
остаются (.gitkeep), .gitignore добавлен.
2026-10-02 21:27:00 +00:00
63 changed files with 175 additions and 158 deletions

42
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,42 @@
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
lint-and-homework:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install ruff==0.14.0 pytest==8.4.2
- name: Ruff (синтаксис и ошибки)
run: ruff check --select E9,F .
- name: Тесты домашних заданий
run: |
cd hws/hw-1 && pytest -q test.py && cd ../..
cd hws/hw-2 && pytest -q test.py
apps:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
app: [labs/lab-1/app, labs/lab-2/app, labs/lab-3/app, labs/lab-4/app, labs/lab-5/app, labs/lab-6/app, ex]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Зависимости
run: |
req=$(dirname ${{ matrix.app }})/requirements.txt
[ -f ${{ matrix.app }}/requirements.txt ] && req=${{ matrix.app }}/requirements.txt
pip install -r $req
- name: Приложение импортируется
working-directory: ${{ matrix.app }}
run: python -c "import app"

12
.gitignore vendored Normal file
View file

@ -0,0 +1,12 @@
__pycache__/
*.py[cod]
.venv/
venv/
.env
*.db
instance/
ex/app/static/uploads/*
!ex/app/static/uploads/.gitkeep
labs/lab-6/app/media/images/*
!labs/lab-6/app/media/images/.gitkeep
.pytest_cache/

56
README.en.md Normal file
View file

@ -0,0 +1,56 @@
# Web Development
[Русский](README.md) · **English**
[![CI](https://github.com/EDeev/web-dev/actions/workflows/ci.yml/badge.svg)](https://github.com/EDeev/web-dev/actions/workflows/ci.yml)
Labs, homework and the exam project for the "Web Development" course at Moscow Polytechnic University:
six Flask apps, 37 Python exercises with tests, and an online library.
**Status:** coursework (Moscow Polytech, group 241-327, 2025/26), completed, archived ·
labs at [web-dev.deev.space](https://web-dev.deev.space), exam at [ex-web.deev.su](https://ex-web.deev.su)
![Exam: online library](docs/screenshots/exam.png)
**Stack:** Python · Flask · Jinja2 · Flask-Login · Flask-SQLAlchemy · Flask-Migrate · SQLite/MySQL · Bootstrap 5 · pytest
| Folder | Contents |
|---|---|
| `labs/lab-1` | blog post template with Flask and Jinja2 |
| `labs/lab-2` | request data: parameters, headers, cookies, forms, phone number validation |
| `labs/lab-3` | sign-in with Flask-Login, protected pages, sessions |
| `labs/lab-4` | user accounts CRUD: database, validation, password hashing |
| `labs/lab-5` | roles and permissions, visit log, reports with CSV export |
| `labs/lab-6` | education portal: course reviews, ratings, pagination, filters |
| `hws/hw-1`, `hws/hw-2` | 37 Python exercises (algorithms, files, decorators, generators, OOP) and 241 tests |
| `ex` | exam: book catalog with search, reviews and roles (admin, moderator, user) |
## Running
```bash
cd labs/lab-3 && pip install -r requirements.txt
cd app && FLASK_DEBUG=1 python app.py
cd ex && pip install -r requirements.txt
python db/db_seed.py # database, roles and test users (passwords are printed)
python run.py
```
`SECRET_KEY` and `FLASK_DEBUG` come from environment variables. Homework tests:
`cd hws/hw-1 && pytest test.py`.
## License
Coursework (Web Development, Moscow Polytechnic University, 2025/26). The code is open for study; there
is no separate license.
## Author
**Egor Deev** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space)
---
<div align="center">
<sub>⭐ If you find this project useful, give it a star on GitHub!</sub>
<p><sub>Made with ❤️ — <a href="https://deev.space">deev.space</a></sub></p>
</div>

106
README.md
View file

@ -1,90 +1,56 @@
# Курс Веб-разработки
[![Python](https://img.shields.io/badge/Python-3776AB?style=flat&logo=python&logoColor=white)](https://www.python.org/)
[![Flask](https://img.shields.io/badge/Flask-000000?style=flat&logo=flask&logoColor=white)](https://flask.palletsprojects.com/)
[![SQLite](https://img.shields.io/badge/SQLite-003B57?style=flat&logo=sqlite&logoColor=white)](https://www.sqlite.org/)
[![Bootstrap](https://img.shields.io/badge/Bootstrap-7952B3?style=flat&logo=bootstrap&logoColor=white)](https://getbootstrap.com/)
# Веб-разработка
Репозиторий содержит выполненные лабораторные работы и домашние задания по курсу "Веб-разработка" в Московском Политехническом университете.
**Русский** · [English](README.en.md)
**Веб-сайт проекта:** [web-dev.deev.space](https://web-dev.deev.space)
[![CI](https://github.com/EDeev/web-dev/actions/workflows/ci.yml/badge.svg)](https://github.com/EDeev/web-dev/actions/workflows/ci.yml)
**Автор:** Деев Егор Викторович, группа 241-327
Лабораторные, домашние задания и экзаменационный проект по курсу «Веб-разработка» в Московском
Политехе: шесть Flask-приложений, 37 задач на Python с тестами и электронная библиотека.
## Структура репозитория
**Статус:** учебный проект (Московский Политех, группа 241-327, 2025/26), завершён, в архиве ·
лабораторные — [web-dev.deev.space](https://web-dev.deev.space), экзамен — [ex-web.deev.su](https://ex-web.deev.su)
### Лабораторные работы
![Экзамен: электронная библиотека](docs/screenshots/exam.png)
#### [Лабораторная работа №1](https://web-dev.deev.space/lab1)
Создание шаблона для отображения записи блога с использованием Flask и Jinja2. Реализация базовой структуры приложения, шаблонов для отображения постов и комментариев.
**Стек:** Python · Flask · Jinja2 · Flask-Login · Flask-SQLAlchemy · Flask-Migrate · SQLite/MySQL · Bootstrap 5 · pytest
**Стек:** Flask, Jinja2, Bootstrap 5
| Папка | Что внутри |
|---|---|
| `labs/lab-1` | шаблон записи блога на Flask и Jinja2 |
| `labs/lab-2` | данные запроса: параметры, заголовки, cookies, формы, проверка телефона |
| `labs/lab-3` | вход через Flask-Login, защищённые страницы, сессии |
| `labs/lab-4` | CRUD учётных записей: база, валидация, хеширование паролей |
| `labs/lab-5` | роли и права, журнал посещений, отчёты с экспортом в CSV |
| `labs/lab-6` | образовательный портал: отзывы к курсам, рейтинг, пагинация, фильтры |
| `hws/hw-1`, `hws/hw-2` | 37 задач на Python (алгоритмы, файлы, декораторы, генераторы, ООП) и 241 тест |
| `ex` | экзамен: каталог книг с поиском, рецензиями и ролями (администратор, модератор, пользователь) |
#### [Лабораторная работа №2](https://web-dev.deev.space/lab2)
Работа с данными запроса. Реализация обработки параметров URL, заголовков, cookies и форм. Валидация номера телефона на стороне сервера.
## Запуск
**Стек:** Flask, регулярные выражения
```bash
cd labs/lab-3 && pip install -r requirements.txt
cd app && FLASK_DEBUG=1 python app.py
#### [Лабораторная работа №3](https://web-dev.deev.space/lab3)
Реализация аутентификации пользователей с использованием Flask-Login. Создание системы входа, защищенных страниц и управления сессиями.
cd ex && pip install -r requirements.txt
python db/db_seed.py # база, роли и тестовые пользователи (пароли выводятся в консоль)
python run.py
```
**Стек:** Flask, Flask-Login, session management
`SECRET_KEY` и `FLASK_DEBUG` задаются переменными окружения. Тесты домашних заданий:
`cd hws/hw-1 && pytest test.py`.
#### [Лабораторная работа №4](https://web-dev.deev.space/lab4)
Разработка CRUD-приложения для управления учетными записями пользователей. Работа с базой данных, валидация данных, хеширование паролей.
## Лицензия
**Стек:** Flask, Flask-SQLAlchemy, MySQL, bcrypt
Учебный проект (Веб-разработка, Московский Политех, 2025/26). Код открыт для изучения, отдельной
лицензии нет.
#### [Лабораторная работа №5](https://web-dev.deev.space/lab5)
Авторизация пользователей и формирование статистических отчетов. Реализация системы ролей, декораторов проверки прав, журнала посещений и экспорта в CSV.
## Автор
**Стек:** Flask, Flask-Login, Blueprints, CSV export
#### [Лабораторная работа №6](https://web-dev.deev.space/lab6)
Доработка образовательного портала: добавление системы отзывов к курсам, рейтинговой системы, пагинации и фильтрации.
**Стек:** Flask, Flask-SQLAlchemy, Flask-Migrate, MySQL
### Домашние задания
#### [Домашнее задание №1](https://github.com/EDeev/web-dev/tree/main/hws/hw-1)
Решение 20 задач на Python: базовые алгоритмы, работа с файлами, регулярные выражения, структуры данных. Покрытие тестами с использованием pytest (60+ тестов).
**Темы:** базовый синтаксис Python, работа с файлами, алгоритмы, структуры данных
#### [Домашнее задание №2](https://github.com/EDeev/web-dev/tree/main/hws/hw-2)
Решение 17 задач на Python: функции, декораторы, генераторы, ООП, работа с файловой системой. Покрытие тестами с использованием pytest (60+ тестов).
**Темы:** функции, декораторы, генераторы, ООП, аргументы командной строки, работа с файлами
## План развития
- Развертывание всех лабораторных работ на хостинге
- Добавление CI/CD pipeline для автоматического тестирования
- Документирование API endpoints
- Рефакторинг кода с применением паттернов проектирования
- Добавление Docker-контейнеризации для упрощения развертывания
## Технологический стек
- **Backend:** Python, Flask, Flask-Login, Flask-SQLAlchemy, Flask-Migrate
- **Frontend:** HTML5, CSS3, Bootstrap 5, Jinja2
- **База данных:** MySQL, SQLite
- **Тестирование:** pytest
- **Деплой:** NGINX, Unit
## Контакты
- Email: egor@deev.space
- Telegram: @Egor_Deev
- GitHub: @EDeev
## Лицензия и использование
Данный репозиторий создан в образовательных целях. Код доступен для изучения и адаптации без указания авторства.
**Деев Егор Викторович** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space)
---
<div align="center">
<sub>⭐ Если проект оказался полезным, поставьте звездочку на GitHub!</sub>
<p><sub>Создано с ❤️ от вашего дорогого - <a href="https://deev.space">deev.space</a> ©</sub></p>
<sub>⭐ Если проект оказался полезным, поставьте звёздочку на GitHub!</sub>
<p><sub>Сделано с ❤️ — <a href="https://deev.space">deev.space</a></sub></p>
</div>

BIN
docs/screenshots/exam.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

BIN
docs/screenshots/labs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

View file

@ -1,2 +0,0 @@
## Сайт развёрнут на домене https://ex-web.deev.su
Тестовые аккаунты (администратор, модератор, пользователь) создаёт `ex/db/db_seed.py`; пароли задаются переменными `SEED_ADMIN_PASSWORD`, `SEED_MODER_PASSWORD`, `SEED_USER_PASSWORD` или генерируются при запуске и выводятся в консоль.

View file

@ -9,7 +9,7 @@ import bleach
import markdown
app = Flask(__name__)
app.secret_key = 'exam-secret-key-2026'
app.secret_key = os.environ.get('SECRET_KEY', 'exam-secret-key-2026')
_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
app.config['UPLOAD_FOLDER'] = os.path.join(os.path.dirname(__file__), 'static', 'uploads')

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#1cc88a"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">КР</text>
</svg>

Before

Width:  |  Height:  |  Size: 254 B

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#858796"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">ГР</text>
</svg>

Before

Width:  |  Height:  |  Size: 254 B

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#e74a3b"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">ВО</text>
</svg>

Before

Width:  |  Height:  |  Size: 254 B

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#f6c23e"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">АВ</text>
</svg>

Before

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 KiB

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#e74a3b"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">МА</text>
</svg>

Before

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 863 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#f6c23e"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">19</text>
</svg>

Before

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#4e73df"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">ПР</text>
</svg>

Before

Width:  |  Height:  |  Size: 254 B

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#1cc88a"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">ДЮ</text>
</svg>

Before

Width:  |  Height:  |  Size: 254 B

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#f6c23e"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">ГА</text>
</svg>

Before

Width:  |  Height:  |  Size: 254 B

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#e74a3b"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">ТР</text>
</svg>

Before

Width:  |  Height:  |  Size: 254 B

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#e74a3b"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">ШЕ</text>
</svg>

Before

Width:  |  Height:  |  Size: 254 B

View file

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="280">
<rect width="200" height="280" fill="#4e73df"/>
<text x="100" y="155" font-family="Arial" font-size="48" font-weight="bold"
fill="white" text-anchor="middle">ВЛ</text>
</svg>

Before

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

View file

@ -8,4 +8,4 @@ if __name__ == '__main__':
with app.app_context():
if not os.path.exists(app.config['DATABASE']):
init_db()
app.run(debug=True)
app.run(debug=os.environ.get('FLASK_DEBUG') == '1')

View file

@ -1,5 +1,4 @@
import random
import math
def circle_square_mk(r, n):
inside = 0

View file

@ -1,4 +1,3 @@
import operator
def person_lister(f):
def inner(people):

View file

@ -2,7 +2,6 @@ import pytest
import math
import os
import subprocess
import tempfile
from fact import fact_it, fact_rec
from show_employee import show_employee
from sum_and_sub import sum_and_sub
@ -11,7 +10,7 @@ from my_sum import my_sum
from email_validation import fun
from fibonacci import fibonacci
from average_scores import compute_average_scores
from plane_angle import Point, plane_angle
from plane_angle import Point
from complex_numbers import Complex
from circle_square_mk import circle_square_mk
from log_decorator import function_logger

View file

@ -1,3 +1,4 @@
import os
import random
from flask import Flask, render_template
from faker import Faker
@ -48,4 +49,4 @@ def about():
return render_template('about.html', title='Об авторе')
if __name__ == '__main__':
app.run(debug=True)
app.run(debug=os.environ.get('FLASK_DEBUG') == '1')

View file

@ -1,3 +1,4 @@
import os
import re
import random
from flask import Flask, render_template, request
@ -104,4 +105,4 @@ def phone():
)
if __name__ == '__main__':
app.run(debug=True)
app.run(debug=os.environ.get('FLASK_DEBUG') == '1')

View file

@ -1,3 +1,4 @@
import os
import re
import random
from flask import Flask, render_template, request, session, redirect, url_for, flash
@ -8,7 +9,7 @@ fake = Faker('ru_RU')
app = Flask(__name__)
application = app
app.secret_key = '1234567890secret'
app.secret_key = os.environ.get('SECRET_KEY', '1234567890secret')
login_manager = LoginManager()
login_manager.init_app(app)
@ -166,4 +167,4 @@ def phone():
)
if __name__ == '__main__':
app.run(debug=True)
app.run(debug=os.environ.get('FLASK_DEBUG') == '1')

View file

@ -1,7 +1,8 @@
import os
import re
import random
from datetime import datetime
from flask import Flask, render_template, request, session, redirect, url_for, flash, abort
from flask import Flask, render_template, request, session, redirect, url_for, flash
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
@ -11,7 +12,7 @@ fake = Faker('ru_RU')
app = Flask(__name__)
application = app
app.secret_key = '1234567890secret'
app.secret_key = os.environ.get('SECRET_KEY', '1234567890secret')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
@ -447,4 +448,4 @@ def change_password():
if __name__ == '__main__':
app.run(debug=True)
app.run(debug=os.environ.get('FLASK_DEBUG') == '1')

Binary file not shown.

View file

@ -7,6 +7,7 @@ MarkupSafe==2.1.1
python-dateutil==2.8.2
six==1.16.0
Werkzeug==2.0.3
Flask-Login
Flask-SQLAlchemy
Flask-Bcrypt
Flask-Login==0.6.3
Flask-SQLAlchemy==2.5.1
SQLAlchemy==1.4.54
Flask-Bcrypt==1.0.1

View file

@ -1,8 +1,9 @@
import os
import re
import random
from functools import wraps
from datetime import datetime
from flask import Flask, render_template, request, session, redirect, url_for, flash, abort
from flask import Flask, render_template, request, session, redirect, url_for, flash
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
@ -12,7 +13,7 @@ fake = Faker('ru_RU')
app = Flask(__name__)
application = app
app.secret_key = '1234567890secret'
app.secret_key = os.environ.get('SECRET_KEY', '1234567890secret')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
@ -515,4 +516,4 @@ with app.app_context():
if __name__ == '__main__':
app.run(debug=True)
app.run(debug=os.environ.get('FLASK_DEBUG') == '1')

Binary file not shown.

View file

@ -51,7 +51,7 @@ def index():
return redirect(url_for('index'))
m = _get_app_module()
db, VisitLog = m.db, m.VisitLog
VisitLog = m.VisitLog
page = request.args.get('page', 1, type=int)
per_page = 10

View file

@ -7,6 +7,7 @@ MarkupSafe==2.1.1
python-dateutil==2.8.2
six==1.16.0
Werkzeug==2.0.3
Flask-Login
Flask-SQLAlchemy
Flask-Bcrypt
Flask-Login==0.6.3
Flask-SQLAlchemy==2.5.1
SQLAlchemy==1.4.54
Flask-Bcrypt==1.0.1

View file

@ -1,6 +1,6 @@
import os
SECRET_KEY = 'secret-key'
SECRET_KEY = os.environ.get('SECRET_KEY', 'secret-key')
SQLALCHEMY_DATABASE_URI = 'sqlite:///project.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False

Binary file not shown.

View file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 483 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 970 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

View file

@ -1,7 +1,6 @@
import os
from typing import Optional, Union, List
from typing import Optional, List
from datetime import datetime
import sqlalchemy as sa
from werkzeug.security import check_password_hash, generate_password_hash
from flask_login import UserMixin
from flask import url_for