Compare commits
29 Commits
start_proj
...
develop
Author | SHA1 | Date | |
---|---|---|---|
8475d83b25 | |||
297ef62fab | |||
f945dc30a1 | |||
d3febb5a6a | |||
4d3a309940 | |||
c2e68881d9 | |||
cdf9bfe072 | |||
50e74ccf38 | |||
52d1b84658 | |||
9cecc960db | |||
985301d27f | |||
30f2dbde98 | |||
54c40985cb | |||
d4722945e9 | |||
e2743db969 | |||
3bc178f2cc | |||
18724c455a | |||
2c6c2ebbe9 | |||
6af1d3c7cb | |||
21a818d71e | |||
c126531e49 | |||
3b63421f5f | |||
d8f8b36469 | |||
009415d261 | |||
9301f984c3 | |||
40274136fe | |||
eb5eb79383 | |||
48be7e96d9 | |||
911d3ef845 |
21
.env
Normal file
21
.env
Normal file
@@ -0,0 +1,21 @@
|
||||
# site basic constants
|
||||
# this info will be shown on site header and footer
|
||||
BRAND=pyproger_test
|
||||
COPYRIGHT_YEAR=2024
|
||||
COPYRIGHT_NAME=test user
|
||||
COPYRIGHT_LINK=mailto:test@mail.com
|
||||
COPYRIGHT_CITY=Some sity
|
||||
|
||||
# sqlalchemy connection section
|
||||
DB_HOST=db_ip_adress
|
||||
DB_PORT=db_port
|
||||
DB_USER=db_user
|
||||
DB_PASS=db_user_password
|
||||
DB_NAME=db_name
|
||||
|
||||
# server run mode
|
||||
MODE=DEV
|
||||
|
||||
# security requared values
|
||||
SECRET_KEY=Some_secret_key
|
||||
SECURITY_PASSWORD_SALT=Some_secret_salt
|
3
.gitignore
vendored
Executable file → Normal file
3
.gitignore
vendored
Executable file → Normal file
@@ -1,3 +1,6 @@
|
||||
pyproger/uploads/*
|
||||
!pyproger/uploads/.gitkeep
|
||||
|
||||
config.ini
|
||||
data/
|
||||
|
||||
|
9
.test.env
Normal file
9
.test.env
Normal file
@@ -0,0 +1,9 @@
|
||||
BRAND=pyproger_test
|
||||
COPYRIGHT_YEAR=2023
|
||||
COPYRIGHT_NAME=TestUser
|
||||
COPYRIGHT_LINK=mailto:test@mail.com
|
||||
COPYRIGHT_CITY=Mysity
|
||||
SECRET_KEY=somesecretkey
|
||||
SECURITY_PASSWORD_SALT=somesecretsolt
|
||||
SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://pi3c:@localhost:5432/pyproger_test
|
||||
|
@@ -55,6 +55,11 @@
|
||||
|
||||
Перейдите в браузере по адресу 127.0.0.1:5000 для доступа к блогу или 127.0.0.1:5000/admin в админ панель
|
||||
|
||||
### TODO
|
||||
- Добавить на страницы постов "Оглавление" со ссылками на статьи
|
||||
- Добавить подписку на статьи
|
||||
- Добавить комментарии к постам
|
||||
|
||||
### Авторы
|
||||
- Сергей Ванюшкин <pi3c@yandex.ru>
|
||||
|
||||
|
@@ -4,41 +4,28 @@ from datetime import datetime as dt
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
dotenv_path = os.path.join(os.path.dirname(__file__), "pyproger", ".env")
|
||||
dotenv_path = os.path.join(os.path.dirname(__file__), ".env")
|
||||
if os.path.exists(dotenv_path):
|
||||
load_dotenv(dotenv_path)
|
||||
|
||||
|
||||
def cls():
|
||||
os.system("cls" if os.name == "nt" else "clear")
|
||||
|
||||
|
||||
with open(dotenv_path, "a") as f:
|
||||
if os.getenv("BRAND") is None:
|
||||
br = input("Введите название блога: ")
|
||||
cls()
|
||||
print("\033[32m{}\033[0m ".format("Введите название проекта."))
|
||||
print(
|
||||
"Это название будет отображаться в строке",
|
||||
"меню и футере на страницах сайта",
|
||||
sep="\n",
|
||||
)
|
||||
br = input("-> ")
|
||||
f.writelines(f"BRAND={br}\n")
|
||||
|
||||
print("Генерирую SECRET_KEY...")
|
||||
if os.getenv("SECRET_KEY") is None:
|
||||
f.writelines(f"SECRET_KEY={uuid.uuid4().hex}\n")
|
||||
print("_Ok_")
|
||||
else:
|
||||
print("SECRET_KEY уже установлен, пропускаю")
|
||||
|
||||
print('Генерирую "Соль"...')
|
||||
if os.getenv("SECURITY_PASSWORD_SALT") is None:
|
||||
f.writelines(f"SECURITY_PASSWORD_SALT={uuid.uuid4().hex}\n")
|
||||
print("_Ok_")
|
||||
else:
|
||||
print("SECURITY_PASSWORD_SALT уже установлен, пропускаю")
|
||||
|
||||
if os.getenv("SQLALCHEMY_DATABASE_URI") is None:
|
||||
print("Настроки подключения к базе данных Posgresql:")
|
||||
login = input("Введите логин пользователя бд: ")
|
||||
passwd = input("Пароль: ")
|
||||
db = input("Название бд (по умолчанию pyprogerdb):") or "pyprogerdb"
|
||||
ip = input("Адрес бд (по умолчанию localhost)") or "localhost"
|
||||
port = input("Порт подключения: (по умолчанию 5432)") or "5432"
|
||||
f.writelines(
|
||||
f"SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://{login}:{passwd}@{ip}:{port}/{db}\n"
|
||||
)
|
||||
|
||||
print("\033[32m{}\033[0m ".format("Настройка блока copyright в футере сайта"))
|
||||
if os.getenv("COPYRIGHT_YEAR") is None:
|
||||
start_date = dt.utcnow().strftime("%Y")
|
||||
f.writelines(f"COPYRIGHT_YEAR={start_date}\n")
|
||||
@@ -61,3 +48,30 @@ with open(dotenv_path, "a") as f:
|
||||
if os.getenv("COPYRIGHT_CITY") is None:
|
||||
name = input("Введите свой город для для футера:")
|
||||
f.writelines(f"COPYRIGHT_CITY={name}\n")
|
||||
|
||||
print("\033[32m{}\033[0m ".format("Генерирую SECRET_KEY..."))
|
||||
if os.getenv("SECRET_KEY") is None:
|
||||
f.writelines(f"SECRET_KEY={uuid.uuid4().hex}\n")
|
||||
print("_Ok_")
|
||||
else:
|
||||
print("SECRET_KEY уже установлен, пропускаю")
|
||||
|
||||
print("\033[32m{}\033[0m ".format('Генерирую "Соль"...'))
|
||||
if os.getenv("SECURITY_PASSWORD_SALT") is None:
|
||||
f.writelines(f"SECURITY_PASSWORD_SALT={uuid.uuid4().hex}\n")
|
||||
print("_Ok_")
|
||||
else:
|
||||
print("SECURITY_PASSWORD_SALT уже установлен, пропускаю")
|
||||
|
||||
if os.getenv("SQLALCHEMY_DATABASE_URI") is None:
|
||||
print(
|
||||
"\033[32m{}\033[0m ".format("Настроки подключения к базе данных Posgresql:")
|
||||
)
|
||||
login = input("Введите логин пользователя бд: ")
|
||||
passwd = input("Пароль: ")
|
||||
db = input("Название бд (по умолчанию pyprogerdb):") or "pyprogerdb"
|
||||
ip = input("Адрес бд (по умолчанию localhost)") or "localhost"
|
||||
port = input("Порт подключения: (по умолчанию 5432)") or "5432"
|
||||
f.writelines(
|
||||
f"SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://{login}:{passwd}@{ip}:{port}/{db}\n"
|
||||
)
|
||||
|
33
migrations/versions/055327bef08e_.py
Normal file
33
migrations/versions/055327bef08e_.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 055327bef08e
|
||||
Revises: 849ff22feb97
|
||||
Create Date: 2023-10-23 09:29:00.193470
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
import flask_security
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '055327bef08e'
|
||||
down_revision = '849ff22feb97'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('page', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('header_description', sa.Text(), nullable=True))
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('page', schema=None) as batch_op:
|
||||
batch_op.drop_column('header_description')
|
||||
|
||||
# ### end Alembic commands ###
|
53
migrations/versions/849ff22feb97_.py
Normal file
53
migrations/versions/849ff22feb97_.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 849ff22feb97
|
||||
Revises: 68537cc1688c
|
||||
Create Date: 2023-10-23 08:34:08.251453
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
import flask_security
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '849ff22feb97'
|
||||
down_revision = '68537cc1688c'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('footer_icons', schema=None) as batch_op:
|
||||
batch_op.create_unique_constraint(None, ['id'])
|
||||
|
||||
with op.batch_alter_table('page', schema=None) as batch_op:
|
||||
batch_op.create_unique_constraint(None, ['id'])
|
||||
|
||||
with op.batch_alter_table('post', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('header_description', sa.Text(), nullable=True))
|
||||
batch_op.create_unique_constraint(None, ['id'])
|
||||
|
||||
with op.batch_alter_table('site_headers', schema=None) as batch_op:
|
||||
batch_op.create_unique_constraint(None, ['id'])
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('site_headers', schema=None) as batch_op:
|
||||
batch_op.drop_constraint(None, type_='unique')
|
||||
|
||||
with op.batch_alter_table('post', schema=None) as batch_op:
|
||||
batch_op.drop_constraint(None, type_='unique')
|
||||
batch_op.drop_column('header_description')
|
||||
|
||||
with op.batch_alter_table('page', schema=None) as batch_op:
|
||||
batch_op.drop_constraint(None, type_='unique')
|
||||
|
||||
with op.batch_alter_table('footer_icons', schema=None) as batch_op:
|
||||
batch_op.drop_constraint(None, type_='unique')
|
||||
|
||||
# ### end Alembic commands ###
|
376
poetry.lock
generated
376
poetry.lock
generated
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "alembic"
|
||||
@@ -19,6 +19,17 @@ typing-extensions = ">=4"
|
||||
[package.extras]
|
||||
tz = ["python-dateutil"]
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
version = "0.6.0"
|
||||
description = "Reusable constraint types to use with typing.Annotated"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"},
|
||||
{file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "babel"
|
||||
version = "2.13.0"
|
||||
@@ -35,13 +46,13 @@ dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
|
||||
|
||||
[[package]]
|
||||
name = "blinker"
|
||||
version = "1.6.2"
|
||||
version = "1.6.3"
|
||||
description = "Fast, simple object-to-object and broadcast signaling"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "blinker-1.6.2-py3-none-any.whl", hash = "sha256:c3d739772abb7bc2860abf5f2ec284223d9ad5c76da018234f6f50d6f31ab1f0"},
|
||||
{file = "blinker-1.6.2.tar.gz", hash = "sha256:4afd3de66ef3a9f8067559fb7a1cbe555c17dcbe15971b05d1b625c3e7abe213"},
|
||||
{file = "blinker-1.6.3-py3-none-any.whl", hash = "sha256:296320d6c28b006eb5e32d4712202dbcdcbf5dc482da298c2f44881c43884aaa"},
|
||||
{file = "blinker-1.6.3.tar.gz", hash = "sha256:152090d27c1c5c722ee7e48504b02d76502811ce02e1523553b4cf8c8b3d3a8d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -222,22 +233,23 @@ Flask = "*"
|
||||
|
||||
[[package]]
|
||||
name = "flask-security-too"
|
||||
version = "5.3.0"
|
||||
version = "5.3.1"
|
||||
description = "Quickly add security features to your Flask application."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "Flask-Security-Too-5.3.0.tar.gz", hash = "sha256:9f5d830913eac66f18845795ae5f7d044bdd0d836aeabccfebadab6a29f79354"},
|
||||
{file = "Flask_Security_Too-5.3.0-py3-none-any.whl", hash = "sha256:c358893d9de3332e523288e6751b51d354973e25e70b0b4a7ef229eca9f910db"},
|
||||
{file = "Flask-Security-Too-5.3.1.tar.gz", hash = "sha256:1dafe00c611ce3811e7fe1686ecd7750938806a1ec3c5a278185f31958895d3c"},
|
||||
{file = "Flask_Security_Too-5.3.1-py3-none-any.whl", hash = "sha256:159ed080dce4a717c2852eac50443221f50b391f5af6f03c82febc3740d572d1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
email-validator = ">=1.1.1"
|
||||
Flask = ">=2.3.0"
|
||||
Flask = ">=2.3.2"
|
||||
Flask-Login = ">=0.6.2"
|
||||
Flask-Principal = ">=0.4.0"
|
||||
Flask-WTF = ">=1.1.1"
|
||||
Flask-WTF = ">=1.1.2"
|
||||
importlib-resources = ">=5.10.0"
|
||||
markupsafe = ">=2.1.0"
|
||||
passlib = ">=1.7.4"
|
||||
wtforms = ">=3.0.0"
|
||||
|
||||
@@ -245,8 +257,8 @@ wtforms = ">=3.0.0"
|
||||
babel = ["babel (>=2.12.1)", "flask-babel (>=3.1.0)"]
|
||||
common = ["bcrypt (>=4.0.1)", "bleach (>=6.0.0)", "flask-mailman (>=0.3.0)"]
|
||||
fsqla = ["flask-sqlalchemy (>=3.0.3)", "sqlalchemy (>=2.0.12)", "sqlalchemy-utils (>=0.41.1)"]
|
||||
low = ["Flask (==2.3.2)", "Flask-Babel (==3.1.0)", "Flask-Login (==0.6.2)", "Flask-Mailman (==0.3.0)", "Flask-SQLAlchemy (==3.0.3)", "Flask-WTF (==1.1.1)", "argon2-cffi (==21.3.0)", "authlib (==1.2.0)", "babel (==2.12.1)", "bcrypt (==4.0.1)", "bleach (==6.0.0)", "itsdangerous (==2.1.2)", "jinja2 (==3.1.2)", "markupsafe (==2.1.2)", "mongoengine (==0.27.0)", "mongomock (==4.1.2)", "peewee (==3.16.2)", "phonenumberslite (==8.13.11)", "pony (==0.7.16)", "python-dateutil (==2.8.2)", "qrcode (==7.4.2)", "requests", "sqlalchemy (==2.0.12)", "sqlalchemy-utils (==0.41.1)", "webauthn (==1.9.0)", "werkzeug (==2.3.3)", "zxcvbn (==4.4.28)"]
|
||||
mfa = ["cryptography (>=40.0.2)", "phonenumberslite (>=8.13.11)", "qrcode (>=7.4.2)", "webauthn (>=1.9.0)"]
|
||||
low = ["Flask (==2.3.2)", "Flask-Babel (==3.1.0)", "Flask-Login (==0.6.2)", "Flask-Mailman (==0.3.0)", "Flask-SQLAlchemy (==3.0.3)", "Flask-WTF (==1.1.2)", "argon2-cffi (==21.3.0)", "authlib (==1.2.0)", "babel (==2.12.1)", "bcrypt (==4.0.1)", "bleach (==6.0.0)", "itsdangerous (==2.1.2)", "jinja2 (==3.1.2)", "markupsafe (==2.1.2)", "mongoengine (==0.27.0)", "mongomock (==4.1.2)", "peewee (==3.16.2)", "phonenumberslite (==8.13.11)", "pony (==0.7.16)", "pydantic (<2.0)", "python-dateutil (==2.8.2)", "qrcode (==7.4.2)", "requests", "sqlalchemy (==2.0.12)", "sqlalchemy-utils (==0.41.1)", "webauthn (==1.11.0)", "werkzeug (==2.3.3)", "zxcvbn (==4.4.28)"]
|
||||
mfa = ["cryptography (>=40.0.2)", "phonenumberslite (>=8.13.11)", "qrcode (>=7.4.2)", "webauthn (>=1.11.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "flask-sqlalchemy"
|
||||
@@ -548,25 +560,237 @@ build-docs = ["cloud-sptheme (>=1.10.1)", "sphinx (>=1.6)", "sphinxcontrib-fullt
|
||||
totp = ["cryptography"]
|
||||
|
||||
[[package]]
|
||||
name = "psycopg2"
|
||||
name = "psycopg2-binary"
|
||||
version = "2.9.9"
|
||||
description = "psycopg2 - Python-PostgreSQL Database Adapter"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "psycopg2-2.9.9-cp310-cp310-win32.whl", hash = "sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516"},
|
||||
{file = "psycopg2-2.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3"},
|
||||
{file = "psycopg2-2.9.9-cp311-cp311-win32.whl", hash = "sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372"},
|
||||
{file = "psycopg2-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981"},
|
||||
{file = "psycopg2-2.9.9-cp37-cp37m-win32.whl", hash = "sha256:5e0d98cade4f0e0304d7d6f25bbfbc5bd186e07b38eac65379309c4ca3193efa"},
|
||||
{file = "psycopg2-2.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:7e2dacf8b009a1c1e843b5213a87f7c544b2b042476ed7755be813eaf4e8347a"},
|
||||
{file = "psycopg2-2.9.9-cp38-cp38-win32.whl", hash = "sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c"},
|
||||
{file = "psycopg2-2.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:bac58c024c9922c23550af2a581998624d6e02350f4ae9c5f0bc642c633a2d5e"},
|
||||
{file = "psycopg2-2.9.9-cp39-cp39-win32.whl", hash = "sha256:c92811b2d4c9b6ea0285942b2e7cac98a59e166d59c588fe5cfe1eda58e72d59"},
|
||||
{file = "psycopg2-2.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913"},
|
||||
{file = "psycopg2-2.9.9.tar.gz", hash = "sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156"},
|
||||
{file = "psycopg2-binary-2.9.9.tar.gz", hash = "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-win32.whl", hash = "sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682"},
|
||||
{file = "psycopg2_binary-2.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-win32.whl", hash = "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d"},
|
||||
{file = "psycopg2_binary-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0605eaed3eb239e87df0d5e3c6489daae3f7388d455d0c0b4df899519c6a38d"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-win32.whl", hash = "sha256:64cf30263844fa208851ebb13b0732ce674d8ec6a0c86a4e160495d299ba3c93"},
|
||||
{file = "psycopg2_binary-2.9.9-cp312-cp312-win_amd64.whl", hash = "sha256:81ff62668af011f9a48787564ab7eded4e9fb17a4a6a74af5ffa6a457400d2ab"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-win32.whl", hash = "sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692"},
|
||||
{file = "psycopg2_binary-2.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-win32.whl", hash = "sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5"},
|
||||
{file = "psycopg2_binary-2.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-win32.whl", hash = "sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90"},
|
||||
{file = "psycopg2_binary-2.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.5.3"
|
||||
description = "Data validation using Python type hints"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pydantic-2.5.3-py3-none-any.whl", hash = "sha256:d0caf5954bee831b6bfe7e338c32b9e30c85dfe080c843680783ac2b631673b4"},
|
||||
{file = "pydantic-2.5.3.tar.gz", hash = "sha256:b3ef57c62535b0941697cce638c08900d87fcb67e29cfa99e8a68f747f393f7a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
annotated-types = ">=0.4.0"
|
||||
pydantic-core = "2.14.6"
|
||||
typing-extensions = ">=4.6.1"
|
||||
|
||||
[package.extras]
|
||||
email = ["email-validator (>=2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.14.6"
|
||||
description = ""
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pydantic_core-2.14.6-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:72f9a942d739f09cd42fffe5dc759928217649f070056f03c70df14f5770acf9"},
|
||||
{file = "pydantic_core-2.14.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6a31d98c0d69776c2576dda4b77b8e0c69ad08e8b539c25c7d0ca0dc19a50d6c"},
|
||||
{file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5aa90562bc079c6c290f0512b21768967f9968e4cfea84ea4ff5af5d917016e4"},
|
||||
{file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:370ffecb5316ed23b667d99ce4debe53ea664b99cc37bfa2af47bc769056d534"},
|
||||
{file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f85f3843bdb1fe80e8c206fe6eed7a1caeae897e496542cee499c374a85c6e08"},
|
||||
{file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9862bf828112e19685b76ca499b379338fd4c5c269d897e218b2ae8fcb80139d"},
|
||||
{file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:036137b5ad0cb0004c75b579445a1efccd072387a36c7f217bb8efd1afbe5245"},
|
||||
{file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92879bce89f91f4b2416eba4429c7b5ca22c45ef4a499c39f0c5c69257522c7c"},
|
||||
{file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0c08de15d50fa190d577e8591f0329a643eeaed696d7771760295998aca6bc66"},
|
||||
{file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:36099c69f6b14fc2c49d7996cbf4f87ec4f0e66d1c74aa05228583225a07b590"},
|
||||
{file = "pydantic_core-2.14.6-cp310-none-win32.whl", hash = "sha256:7be719e4d2ae6c314f72844ba9d69e38dff342bc360379f7c8537c48e23034b7"},
|
||||
{file = "pydantic_core-2.14.6-cp310-none-win_amd64.whl", hash = "sha256:36fa402dcdc8ea7f1b0ddcf0df4254cc6b2e08f8cd80e7010d4c4ae6e86b2a87"},
|
||||
{file = "pydantic_core-2.14.6-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:dea7fcd62915fb150cdc373212141a30037e11b761fbced340e9db3379b892d4"},
|
||||
{file = "pydantic_core-2.14.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421"},
|
||||
{file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b027c86c66b8627eb90e57aee1f526df77dc6d8b354ec498be9a757d513b92b"},
|
||||
{file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:00b1087dabcee0b0ffd104f9f53d7d3eaddfaa314cdd6726143af6bc713aa27e"},
|
||||
{file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:75ec284328b60a4e91010c1acade0c30584f28a1f345bc8f72fe8b9e46ec6a96"},
|
||||
{file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e1f4744eea1501404b20b0ac059ff7e3f96a97d3e3f48ce27a139e053bb370b"},
|
||||
{file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2602177668f89b38b9f84b7b3435d0a72511ddef45dc14446811759b82235a1"},
|
||||
{file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c8edaea3089bf908dd27da8f5d9e395c5b4dc092dbcce9b65e7156099b4b937"},
|
||||
{file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:478e9e7b360dfec451daafe286998d4a1eeaecf6d69c427b834ae771cad4b622"},
|
||||
{file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b6ca36c12a5120bad343eef193cc0122928c5c7466121da7c20f41160ba00ba2"},
|
||||
{file = "pydantic_core-2.14.6-cp311-none-win32.whl", hash = "sha256:2b8719037e570639e6b665a4050add43134d80b687288ba3ade18b22bbb29dd2"},
|
||||
{file = "pydantic_core-2.14.6-cp311-none-win_amd64.whl", hash = "sha256:78ee52ecc088c61cce32b2d30a826f929e1708f7b9247dc3b921aec367dc1b23"},
|
||||
{file = "pydantic_core-2.14.6-cp311-none-win_arm64.whl", hash = "sha256:a19b794f8fe6569472ff77602437ec4430f9b2b9ec7a1105cfd2232f9ba355e6"},
|
||||
{file = "pydantic_core-2.14.6-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:667aa2eac9cd0700af1ddb38b7b1ef246d8cf94c85637cbb03d7757ca4c3fdec"},
|
||||
{file = "pydantic_core-2.14.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cdee837710ef6b56ebd20245b83799fce40b265b3b406e51e8ccc5b85b9099b7"},
|
||||
{file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c5bcf3414367e29f83fd66f7de64509a8fd2368b1edf4351e862910727d3e51"},
|
||||
{file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a92ae76f75d1915806b77cf459811e772d8f71fd1e4339c99750f0e7f6324f"},
|
||||
{file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a983cca5ed1dd9a35e9e42ebf9f278d344603bfcb174ff99a5815f953925140a"},
|
||||
{file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cb92f9061657287eded380d7dc455bbf115430b3aa4741bdc662d02977e7d0af"},
|
||||
{file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4ace1e220b078c8e48e82c081e35002038657e4b37d403ce940fa679e57113b"},
|
||||
{file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef633add81832f4b56d3b4c9408b43d530dfca29e68fb1b797dcb861a2c734cd"},
|
||||
{file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7e90d6cc4aad2cc1f5e16ed56e46cebf4877c62403a311af20459c15da76fd91"},
|
||||
{file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e8a5ac97ea521d7bde7621d86c30e86b798cdecd985723c4ed737a2aa9e77d0c"},
|
||||
{file = "pydantic_core-2.14.6-cp312-none-win32.whl", hash = "sha256:f27207e8ca3e5e021e2402ba942e5b4c629718e665c81b8b306f3c8b1ddbb786"},
|
||||
{file = "pydantic_core-2.14.6-cp312-none-win_amd64.whl", hash = "sha256:b3e5fe4538001bb82e2295b8d2a39356a84694c97cb73a566dc36328b9f83b40"},
|
||||
{file = "pydantic_core-2.14.6-cp312-none-win_arm64.whl", hash = "sha256:64634ccf9d671c6be242a664a33c4acf12882670b09b3f163cd00a24cffbd74e"},
|
||||
{file = "pydantic_core-2.14.6-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:24368e31be2c88bd69340fbfe741b405302993242ccb476c5c3ff48aeee1afe0"},
|
||||
{file = "pydantic_core-2.14.6-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:e33b0834f1cf779aa839975f9d8755a7c2420510c0fa1e9fa0497de77cd35d2c"},
|
||||
{file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6af4b3f52cc65f8a0bc8b1cd9676f8c21ef3e9132f21fed250f6958bd7223bed"},
|
||||
{file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15687d7d7f40333bd8266f3814c591c2e2cd263fa2116e314f60d82086e353a"},
|
||||
{file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:095b707bb287bfd534044166ab767bec70a9bba3175dcdc3371782175c14e43c"},
|
||||
{file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94fc0e6621e07d1e91c44e016cc0b189b48db053061cc22d6298a611de8071bb"},
|
||||
{file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce830e480f6774608dedfd4a90c42aac4a7af0a711f1b52f807130c2e434c06"},
|
||||
{file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a306cdd2ad3a7d795d8e617a58c3a2ed0f76c8496fb7621b6cd514eb1532cae8"},
|
||||
{file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2f5fa187bde8524b1e37ba894db13aadd64faa884657473b03a019f625cee9a8"},
|
||||
{file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:438027a975cc213a47c5d70672e0d29776082155cfae540c4e225716586be75e"},
|
||||
{file = "pydantic_core-2.14.6-cp37-none-win32.whl", hash = "sha256:f96ae96a060a8072ceff4cfde89d261837b4294a4f28b84a28765470d502ccc6"},
|
||||
{file = "pydantic_core-2.14.6-cp37-none-win_amd64.whl", hash = "sha256:e646c0e282e960345314f42f2cea5e0b5f56938c093541ea6dbf11aec2862391"},
|
||||
{file = "pydantic_core-2.14.6-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:db453f2da3f59a348f514cfbfeb042393b68720787bbef2b4c6068ea362c8149"},
|
||||
{file = "pydantic_core-2.14.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3860c62057acd95cc84044e758e47b18dcd8871a328ebc8ccdefd18b0d26a21b"},
|
||||
{file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36026d8f99c58d7044413e1b819a67ca0e0b8ebe0f25e775e6c3d1fabb3c38fb"},
|
||||
{file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ed1af8692bd8d2a29d702f1a2e6065416d76897d726e45a1775b1444f5928a7"},
|
||||
{file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:314ccc4264ce7d854941231cf71b592e30d8d368a71e50197c905874feacc8a8"},
|
||||
{file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:982487f8931067a32e72d40ab6b47b1628a9c5d344be7f1a4e668fb462d2da42"},
|
||||
{file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dbe357bc4ddda078f79d2a36fc1dd0494a7f2fad83a0a684465b6f24b46fe80"},
|
||||
{file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2f6ffc6701a0eb28648c845f4945a194dc7ab3c651f535b81793251e1185ac3d"},
|
||||
{file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7f5025db12fc6de7bc1104d826d5aee1d172f9ba6ca936bf6474c2148ac336c1"},
|
||||
{file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dab03ed811ed1c71d700ed08bde8431cf429bbe59e423394f0f4055f1ca0ea60"},
|
||||
{file = "pydantic_core-2.14.6-cp38-none-win32.whl", hash = "sha256:dfcbebdb3c4b6f739a91769aea5ed615023f3c88cb70df812849aef634c25fbe"},
|
||||
{file = "pydantic_core-2.14.6-cp38-none-win_amd64.whl", hash = "sha256:99b14dbea2fdb563d8b5a57c9badfcd72083f6006caf8e126b491519c7d64ca8"},
|
||||
{file = "pydantic_core-2.14.6-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:4ce8299b481bcb68e5c82002b96e411796b844d72b3e92a3fbedfe8e19813eab"},
|
||||
{file = "pydantic_core-2.14.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9a9d92f10772d2a181b5ca339dee066ab7d1c9a34ae2421b2a52556e719756f"},
|
||||
{file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0"},
|
||||
{file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4f86f1f318e56f5cbb282fe61eb84767aee743ebe32c7c0834690ebea50c0a6b"},
|
||||
{file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86ce5fcfc3accf3a07a729779d0b86c5d0309a4764c897d86c11089be61da160"},
|
||||
{file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dcf1978be02153c6a31692d4fbcc2a3f1db9da36039ead23173bc256ee3b91b"},
|
||||
{file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eedf97be7bc3dbc8addcef4142f4b4164066df0c6f36397ae4aaed3eb187d8ab"},
|
||||
{file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5f916acf8afbcab6bacbb376ba7dc61f845367901ecd5e328fc4d4aef2fcab0"},
|
||||
{file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8a14c192c1d724c3acbfb3f10a958c55a2638391319ce8078cb36c02283959b9"},
|
||||
{file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0348b1dc6b76041516e8a854ff95b21c55f5a411c3297d2ca52f5528e49d8411"},
|
||||
{file = "pydantic_core-2.14.6-cp39-none-win32.whl", hash = "sha256:de2a0645a923ba57c5527497daf8ec5df69c6eadf869e9cd46e86349146e5975"},
|
||||
{file = "pydantic_core-2.14.6-cp39-none-win_amd64.whl", hash = "sha256:aca48506a9c20f68ee61c87f2008f81f8ee99f8d7f0104bff3c47e2d148f89d9"},
|
||||
{file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d5c28525c19f5bb1e09511669bb57353d22b94cf8b65f3a8d141c389a55dec95"},
|
||||
{file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:78d0768ee59baa3de0f4adac9e3748b4b1fffc52143caebddfd5ea2961595277"},
|
||||
{file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b93785eadaef932e4fe9c6e12ba67beb1b3f1e5495631419c784ab87e975670"},
|
||||
{file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a874f21f87c485310944b2b2734cd6d318765bcbb7515eead33af9641816506e"},
|
||||
{file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89f4477d915ea43b4ceea6756f63f0288941b6443a2b28c69004fe07fde0d0d"},
|
||||
{file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:172de779e2a153d36ee690dbc49c6db568d7b33b18dc56b69a7514aecbcf380d"},
|
||||
{file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dfcebb950aa7e667ec226a442722134539e77c575f6cfaa423f24371bb8d2e94"},
|
||||
{file = "pydantic_core-2.14.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:55a23dcd98c858c0db44fc5c04fc7ed81c4b4d33c653a7c45ddaebf6563a2f66"},
|
||||
{file = "pydantic_core-2.14.6-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4241204e4b36ab5ae466ecec5c4c16527a054c69f99bba20f6f75232a6a534e2"},
|
||||
{file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e574de99d735b3fc8364cba9912c2bec2da78775eba95cbb225ef7dda6acea24"},
|
||||
{file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1302a54f87b5cd8528e4d6d1bf2133b6aa7c6122ff8e9dc5220fbc1e07bffebd"},
|
||||
{file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8e81e4b55930e5ffab4a68db1af431629cf2e4066dbdbfef65348b8ab804ea8"},
|
||||
{file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c99462ffc538717b3e60151dfaf91125f637e801f5ab008f81c402f1dff0cd0f"},
|
||||
{file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e4cf2d5829f6963a5483ec01578ee76d329eb5caf330ecd05b3edd697e7d768a"},
|
||||
{file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cf10b7d58ae4a1f07fccbf4a0a956d705356fea05fb4c70608bb6fa81d103cda"},
|
||||
{file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:399ac0891c284fa8eb998bcfa323f2234858f5d2efca3950ae58c8f88830f145"},
|
||||
{file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c6a5c79b28003543db3ba67d1df336f253a87d3112dac3a51b94f7d48e4c0e1"},
|
||||
{file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599c87d79cab2a6a2a9df4aefe0455e61e7d2aeede2f8577c1b7c0aec643ee8e"},
|
||||
{file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43e166ad47ba900f2542a80d83f9fc65fe99eb63ceec4debec160ae729824052"},
|
||||
{file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3a0b5db001b98e1c649dd55afa928e75aa4087e587b9524a4992316fa23c9fba"},
|
||||
{file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:747265448cb57a9f37572a488a57d873fd96bf51e5bb7edb52cfb37124516da4"},
|
||||
{file = "pydantic_core-2.14.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7ebe3416785f65c28f4f9441e916bfc8a54179c8dea73c23023f7086fa601c5d"},
|
||||
{file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:86c963186ca5e50d5c8287b1d1c9d3f8f024cbe343d048c5bd282aec2d8641f2"},
|
||||
{file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e0641b506486f0b4cd1500a2a65740243e8670a2549bb02bc4556a83af84ae03"},
|
||||
{file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71d72ca5eaaa8d38c8df16b7deb1a2da4f650c41b58bb142f3fb75d5ad4a611f"},
|
||||
{file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27e524624eace5c59af499cd97dc18bb201dc6a7a2da24bfc66ef151c69a5f2a"},
|
||||
{file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3dde6cac75e0b0902778978d3b1646ca9f438654395a362cb21d9ad34b24acf"},
|
||||
{file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:00646784f6cd993b1e1c0e7b0fdcbccc375d539db95555477771c27555e3c556"},
|
||||
{file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:23598acb8ccaa3d1d875ef3b35cb6376535095e9405d91a3d57a8c7db5d29341"},
|
||||
{file = "pydantic_core-2.14.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7f41533d7e3cf9520065f610b41ac1c76bc2161415955fbcead4981b22c7611e"},
|
||||
{file = "pydantic_core-2.14.6.tar.gz", hash = "sha256:1fd0c1d395372843fba13a51c28e3bb9d59bd7aebfeb17358ffaaa1e4dbbe948"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-settings"
|
||||
version = "2.1.0"
|
||||
description = "Settings management using Pydantic"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pydantic_settings-2.1.0-py3-none-any.whl", hash = "sha256:7621c0cb5d90d1140d2f0ef557bdf03573aac7035948109adf2574770b77605a"},
|
||||
{file = "pydantic_settings-2.1.0.tar.gz", hash = "sha256:26b1492e0a24755626ac5e6d715e9077ab7ad4fb5f19a8b7ed7011d52f36141c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pydantic = ">=2.3.0"
|
||||
python-dotenv = ">=0.21.0"
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.0.0"
|
||||
@@ -594,52 +818,60 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlalchemy"
|
||||
version = "2.0.21"
|
||||
version = "2.0.22"
|
||||
description = "Database Abstraction Library"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "SQLAlchemy-2.0.21-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1e7dc99b23e33c71d720c4ae37ebb095bebebbd31a24b7d99dfc4753d2803ede"},
|
||||
{file = "SQLAlchemy-2.0.21-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7f0c4ee579acfe6c994637527c386d1c22eb60bc1c1d36d940d8477e482095d4"},
|
||||
{file = "SQLAlchemy-2.0.21-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f7d57a7e140efe69ce2d7b057c3f9a595f98d0bbdfc23fd055efdfbaa46e3a5"},
|
||||
{file = "SQLAlchemy-2.0.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca38746eac23dd7c20bec9278d2058c7ad662b2f1576e4c3dbfcd7c00cc48fa"},
|
||||
{file = "SQLAlchemy-2.0.21-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3cf229704074bce31f7f47d12883afee3b0a02bb233a0ba45ddbfe542939cca4"},
|
||||
{file = "SQLAlchemy-2.0.21-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fb87f763b5d04a82ae84ccff25554ffd903baafba6698e18ebaf32561f2fe4aa"},
|
||||
{file = "SQLAlchemy-2.0.21-cp310-cp310-win32.whl", hash = "sha256:89e274604abb1a7fd5c14867a412c9d49c08ccf6ce3e1e04fffc068b5b6499d4"},
|
||||
{file = "SQLAlchemy-2.0.21-cp310-cp310-win_amd64.whl", hash = "sha256:e36339a68126ffb708dc6d1948161cea2a9e85d7d7b0c54f6999853d70d44430"},
|
||||
{file = "SQLAlchemy-2.0.21-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bf8eebccc66829010f06fbd2b80095d7872991bfe8415098b9fe47deaaa58063"},
|
||||
{file = "SQLAlchemy-2.0.21-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b977bfce15afa53d9cf6a632482d7968477625f030d86a109f7bdfe8ce3c064a"},
|
||||
{file = "SQLAlchemy-2.0.21-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ff3dc2f60dbf82c9e599c2915db1526d65415be323464f84de8db3e361ba5b9"},
|
||||
{file = "SQLAlchemy-2.0.21-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44ac5c89b6896f4740e7091f4a0ff2e62881da80c239dd9408f84f75a293dae9"},
|
||||
{file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:87bf91ebf15258c4701d71dcdd9c4ba39521fb6a37379ea68088ce8cd869b446"},
|
||||
{file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b69f1f754d92eb1cc6b50938359dead36b96a1dcf11a8670bff65fd9b21a4b09"},
|
||||
{file = "SQLAlchemy-2.0.21-cp311-cp311-win32.whl", hash = "sha256:af520a730d523eab77d754f5cf44cc7dd7ad2d54907adeb3233177eeb22f271b"},
|
||||
{file = "SQLAlchemy-2.0.21-cp311-cp311-win_amd64.whl", hash = "sha256:141675dae56522126986fa4ca713739d00ed3a6f08f3c2eb92c39c6dfec463ce"},
|
||||
{file = "SQLAlchemy-2.0.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7614f1eab4336df7dd6bee05bc974f2b02c38d3d0c78060c5faa4cd1ca2af3b8"},
|
||||
{file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d59cb9e20d79686aa473e0302e4a82882d7118744d30bb1dfb62d3c47141b3ec"},
|
||||
{file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a95aa0672e3065d43c8aa80080cdd5cc40fe92dc873749e6c1cf23914c4b83af"},
|
||||
{file = "SQLAlchemy-2.0.21-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8c323813963b2503e54d0944813cd479c10c636e3ee223bcbd7bd478bf53c178"},
|
||||
{file = "SQLAlchemy-2.0.21-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:419b1276b55925b5ac9b4c7044e999f1787c69761a3c9756dec6e5c225ceca01"},
|
||||
{file = "SQLAlchemy-2.0.21-cp37-cp37m-win32.whl", hash = "sha256:4615623a490e46be85fbaa6335f35cf80e61df0783240afe7d4f544778c315a9"},
|
||||
{file = "SQLAlchemy-2.0.21-cp37-cp37m-win_amd64.whl", hash = "sha256:cca720d05389ab1a5877ff05af96551e58ba65e8dc65582d849ac83ddde3e231"},
|
||||
{file = "SQLAlchemy-2.0.21-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b4eae01faee9f2b17f08885e3f047153ae0416648f8e8c8bd9bc677c5ce64be9"},
|
||||
{file = "SQLAlchemy-2.0.21-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3eb7c03fe1cd3255811cd4e74db1ab8dca22074d50cd8937edf4ef62d758cdf4"},
|
||||
{file = "SQLAlchemy-2.0.21-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2d494b6a2a2d05fb99f01b84cc9af9f5f93bf3e1e5dbdafe4bed0c2823584c1"},
|
||||
{file = "SQLAlchemy-2.0.21-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b19ae41ef26c01a987e49e37c77b9ad060c59f94d3b3efdfdbf4f3daaca7b5fe"},
|
||||
{file = "SQLAlchemy-2.0.21-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fc6b15465fabccc94bf7e38777d665b6a4f95efd1725049d6184b3a39fd54880"},
|
||||
{file = "SQLAlchemy-2.0.21-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:014794b60d2021cc8ae0f91d4d0331fe92691ae5467a00841f7130fe877b678e"},
|
||||
{file = "SQLAlchemy-2.0.21-cp38-cp38-win32.whl", hash = "sha256:0268256a34806e5d1c8f7ee93277d7ea8cc8ae391f487213139018b6805aeaf6"},
|
||||
{file = "SQLAlchemy-2.0.21-cp38-cp38-win_amd64.whl", hash = "sha256:73c079e21d10ff2be54a4699f55865d4b275fd6c8bd5d90c5b1ef78ae0197301"},
|
||||
{file = "SQLAlchemy-2.0.21-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:785e2f2c1cb50d0a44e2cdeea5fd36b5bf2d79c481c10f3a88a8be4cfa2c4615"},
|
||||
{file = "SQLAlchemy-2.0.21-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c111cd40910ffcb615b33605fc8f8e22146aeb7933d06569ac90f219818345ef"},
|
||||
{file = "SQLAlchemy-2.0.21-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9cba4e7369de663611ce7460a34be48e999e0bbb1feb9130070f0685e9a6b66"},
|
||||
{file = "SQLAlchemy-2.0.21-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50a69067af86ec7f11a8e50ba85544657b1477aabf64fa447fd3736b5a0a4f67"},
|
||||
{file = "SQLAlchemy-2.0.21-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ccb99c3138c9bde118b51a289d90096a3791658da9aea1754667302ed6564f6e"},
|
||||
{file = "SQLAlchemy-2.0.21-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:513fd5b6513d37e985eb5b7ed89da5fd9e72354e3523980ef00d439bc549c9e9"},
|
||||
{file = "SQLAlchemy-2.0.21-cp39-cp39-win32.whl", hash = "sha256:f9fefd6298433b6e9188252f3bff53b9ff0443c8fde27298b8a2b19f6617eeb9"},
|
||||
{file = "SQLAlchemy-2.0.21-cp39-cp39-win_amd64.whl", hash = "sha256:2e617727fe4091cedb3e4409b39368f424934c7faa78171749f704b49b4bb4ce"},
|
||||
{file = "SQLAlchemy-2.0.21-py3-none-any.whl", hash = "sha256:ea7da25ee458d8f404b93eb073116156fd7d8c2a776d8311534851f28277b4ce"},
|
||||
{file = "SQLAlchemy-2.0.21.tar.gz", hash = "sha256:05b971ab1ac2994a14c56b35eaaa91f86ba080e9ad481b20d99d77f381bb6258"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f146c61ae128ab43ea3a0955de1af7e1633942c2b2b4985ac51cc292daf33222"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:875de9414393e778b655a3d97d60465eb3fae7c919e88b70cc10b40b9f56042d"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13790cb42f917c45c9c850b39b9941539ca8ee7917dacf099cc0b569f3d40da7"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e04ab55cf49daf1aeb8c622c54d23fa4bec91cb051a43cc24351ba97e1dd09f5"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a42c9fa3abcda0dcfad053e49c4f752eef71ecd8c155221e18b99d4224621176"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:14cd3bcbb853379fef2cd01e7c64a5d6f1d005406d877ed9509afb7a05ff40a5"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-win32.whl", hash = "sha256:d143c5a9dada696bcfdb96ba2de4a47d5a89168e71d05a076e88a01386872f97"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-win_amd64.whl", hash = "sha256:ccd87c25e4c8559e1b918d46b4fa90b37f459c9b4566f1dfbce0eb8122571547"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4f6ff392b27a743c1ad346d215655503cec64405d3b694228b3454878bf21590"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f776c2c30f0e5f4db45c3ee11a5f2a8d9de68e81eb73ec4237de1e32e04ae81c"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8f1792d20d2f4e875ce7a113f43c3561ad12b34ff796b84002a256f37ce9437"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d80eeb5189d7d4b1af519fc3f148fe7521b9dfce8f4d6a0820e8f5769b005051"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:69fd9e41cf9368afa034e1c81f3570afb96f30fcd2eb1ef29cb4d9371c6eece2"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54bcceaf4eebef07dadfde424f5c26b491e4a64e61761dea9459103ecd6ccc95"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-win32.whl", hash = "sha256:7ee7ccf47aa503033b6afd57efbac6b9e05180f492aeed9fcf70752556f95624"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-win_amd64.whl", hash = "sha256:b560f075c151900587ade06706b0c51d04b3277c111151997ea0813455378ae0"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2c9bac865ee06d27a1533471405ad240a6f5d83195eca481f9fc4a71d8b87df8"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:625b72d77ac8ac23da3b1622e2da88c4aedaee14df47c8432bf8f6495e655de2"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b39a6e21110204a8c08d40ff56a73ba542ec60bab701c36ce721e7990df49fb9"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53a766cb0b468223cafdf63e2d37f14a4757476157927b09300c8c5832d88560"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0e1ce8ebd2e040357dde01a3fb7d30d9b5736b3e54a94002641dfd0aa12ae6ce"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:505f503763a767556fa4deae5194b2be056b64ecca72ac65224381a0acab7ebe"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-win32.whl", hash = "sha256:154a32f3c7b00de3d090bc60ec8006a78149e221f1182e3edcf0376016be9396"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-win_amd64.whl", hash = "sha256:129415f89744b05741c6f0b04a84525f37fbabe5dc3774f7edf100e7458c48cd"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3940677d341f2b685a999bffe7078697b5848a40b5f6952794ffcf3af150c301"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55914d45a631b81a8a2cb1a54f03eea265cf1783241ac55396ec6d735be14883"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2096d6b018d242a2bcc9e451618166f860bb0304f590d205173d317b69986c95"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:19c6986cf2fb4bc8e0e846f97f4135a8e753b57d2aaaa87c50f9acbe606bd1db"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6ac28bd6888fe3c81fbe97584eb0b96804bd7032d6100b9701255d9441373ec1"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-win32.whl", hash = "sha256:cb9a758ad973e795267da334a92dd82bb7555cb36a0960dcabcf724d26299db8"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-win_amd64.whl", hash = "sha256:40b1206a0d923e73aa54f0a6bd61419a96b914f1cd19900b6c8226899d9742ad"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3aa1472bf44f61dd27987cd051f1c893b7d3b17238bff8c23fceaef4f1133868"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:56a7e2bb639df9263bf6418231bc2a92a773f57886d371ddb7a869a24919face"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ccca778c0737a773a1ad86b68bda52a71ad5950b25e120b6eb1330f0df54c3d0"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6c3e9350f9fb16de5b5e5fbf17b578811a52d71bb784cc5ff71acb7de2a7f9"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:564e9f9e4e6466273dbfab0e0a2e5fe819eec480c57b53a2cdee8e4fdae3ad5f"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:af66001d7b76a3fab0d5e4c1ec9339ac45748bc4a399cbc2baa48c1980d3c1f4"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-win32.whl", hash = "sha256:9e55dff5ec115316dd7a083cdc1a52de63693695aecf72bc53a8e1468ce429e5"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-win_amd64.whl", hash = "sha256:4e869a8ff7ee7a833b74868a0887e8462445ec462432d8cbeff5e85f475186da"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9886a72c8e6371280cb247c5d32c9c8fa141dc560124348762db8a8b236f8692"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a571bc8ac092a3175a1d994794a8e7a1f2f651e7c744de24a19b4f740fe95034"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8db5ba8b7da759b727faebc4289a9e6a51edadc7fc32207a30f7c6203a181592"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b0b3f2686c3f162123adba3cb8b626ed7e9b8433ab528e36ed270b4f70d1cdb"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c1fea8c0abcb070ffe15311853abfda4e55bf7dc1d4889497b3403629f3bf00"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4bb062784f37b2d75fd9b074c8ec360ad5df71f933f927e9e95c50eb8e05323c"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-win32.whl", hash = "sha256:58a3aba1bfb32ae7af68da3f277ed91d9f57620cf7ce651db96636790a78b736"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-win_amd64.whl", hash = "sha256:92e512a6af769e4725fa5b25981ba790335d42c5977e94ded07db7d641490a85"},
|
||||
{file = "SQLAlchemy-2.0.22-py3-none-any.whl", hash = "sha256:3076740335e4aaadd7deb3fe6dcb96b3015f1613bd190a4e1634e1b99b02ec86"},
|
||||
{file = "SQLAlchemy-2.0.22.tar.gz", hash = "sha256:5434cc601aa17570d79e5377f5fd45ff92f9379e2abed0be5e8c2fba8d353d2b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -700,22 +932,22 @@ watchdog = ["watchdog (>=2.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "wtforms"
|
||||
version = "3.0.1"
|
||||
version = "3.1.0"
|
||||
description = "Form validation and rendering for Python web development."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "WTForms-3.0.1-py3-none-any.whl", hash = "sha256:837f2f0e0ca79481b92884962b914eba4e72b7a2daaf1f939c890ed0124b834b"},
|
||||
{file = "WTForms-3.0.1.tar.gz", hash = "sha256:6b351bbb12dd58af57ffef05bc78425d08d1914e0fd68ee14143b7ade023c5bc"},
|
||||
{file = "wtforms-3.1.0-py3-none-any.whl", hash = "sha256:addd7899004fdf9318eb711d33aae9c1973fe80378257b7383e06de2eff7c559"},
|
||||
{file = "wtforms-3.1.0.tar.gz", hash = "sha256:4edd15771630289a5fa343d58822f72749822ca5a39dd33f92ee917cf72b954b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
MarkupSafe = "*"
|
||||
markupsafe = "*"
|
||||
|
||||
[package.extras]
|
||||
email = ["email-validator"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.11"
|
||||
content-hash = "8e8742eb5d336c47334b669f8ef8115f21dc6ce2d555b6941da918fe054bb9f8"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "5fd8b7e353d903e43f875ec2416e7d71cef5f62a6455a22fde3f875fb9e795b9"
|
||||
|
@@ -1,5 +1,4 @@
|
||||
from flask_admin import Admin
|
||||
from flask_ckeditor import CKEditor
|
||||
|
||||
admin = Admin(
|
||||
name="Админ панель",
|
||||
|
@@ -72,6 +72,7 @@ class PostView(MyAdminView):
|
||||
tags="Тэги",
|
||||
slug="Слаг",
|
||||
title="Заголовок",
|
||||
header_description="description заголовок в head страницы",
|
||||
description="Краткое описание статьи",
|
||||
author="Автор",
|
||||
published="Опубликовано",
|
||||
@@ -92,6 +93,7 @@ class PostView(MyAdminView):
|
||||
class PageView(MyAdminView):
|
||||
column_labels = dict(
|
||||
name="Название страницы",
|
||||
header_description="description заголовок в head страницы",
|
||||
slug="URL страницы",
|
||||
text="Содержимое страницы",
|
||||
)
|
||||
|
@@ -1,40 +1,30 @@
|
||||
import os
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from flask import Flask, render_template_string, url_for
|
||||
from flask import Flask, render_template_string, request, send_from_directory, url_for
|
||||
from flask_admin import helpers
|
||||
from flask_ckeditor import CKEditor
|
||||
from flask_ckeditor import CKEditor, upload_fail, upload_success
|
||||
from flask_migrate import Migrate
|
||||
from flask_security.core import Security
|
||||
|
||||
from pyproger.admin.views import FooterLinksView
|
||||
from pyproger.dbase import Role, User, db, user_datastore
|
||||
from pyproger.dbase.database import (get_footer_links, get_headers,
|
||||
get_menu_items)
|
||||
from pyproger.dbase.models import (FooterContactLinks, Page, Post, SiteHeaders,
|
||||
Tag)
|
||||
from pyproger.dbase.database import get_footer_links, get_headers, get_menu_items
|
||||
from pyproger.dbase.models import FooterContactLinks, Page, Post, SiteHeaders, Tag
|
||||
|
||||
from pyproger.config import settings
|
||||
|
||||
def create_app(test_config=None):
|
||||
def create_app():
|
||||
app = Flask(__name__)
|
||||
|
||||
if test_config is None:
|
||||
app.config.from_pyfile("config.py", silent=True)
|
||||
dotenv_path = os.path.join(os.path.dirname(__file__), ".env")
|
||||
if os.path.exists(dotenv_path):
|
||||
load_dotenv(dotenv_path)
|
||||
app.config["SECRET_KEY"] = os.getenv("SECRET_KEY")
|
||||
app.config["SECURITY_PASSWORD_SALT"] = os.getenv("SECURITY_PASSWORD_SALT")
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv("SQLALCHEMY_DATABASE_URI")
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = settings.DB_URL
|
||||
app.config["MYCOPYRIGHT"] = {
|
||||
"year": os.getenv("COPYRIGHT_YEAR"),
|
||||
"name": os.getenv("COPYRIGHT_NAME"),
|
||||
"link": os.getenv("COPYRIGHT_LINK"),
|
||||
"city": os.getenv("COPYRIGHT_CITY"),
|
||||
"year": settings.COPYRIGHT_YEAR,
|
||||
"name": settings.COPYRIGHT_NAME,
|
||||
"link": settings.COPYRIGHT_LINK,
|
||||
"city": settings.COPYRIGHT_CITY,
|
||||
}
|
||||
app.config["BRAND"] = os.getenv("BRAND")
|
||||
else:
|
||||
app.config.from_mapping(test_config)
|
||||
for key, val in settings.__dict__.items():
|
||||
app.config[key] = val
|
||||
|
||||
from .translations import babel
|
||||
from .translations import bp as bp_translate
|
||||
@@ -57,8 +47,14 @@ def create_app(test_config=None):
|
||||
|
||||
admin.init_app(app)
|
||||
|
||||
from pyproger.admin.views import (HeadersView, PageView, PostView,
|
||||
RoleView, TagView, UserView)
|
||||
from pyproger.admin.views import (
|
||||
HeadersView,
|
||||
PageView,
|
||||
PostView,
|
||||
RoleView,
|
||||
TagView,
|
||||
UserView,
|
||||
)
|
||||
|
||||
admin.add_view(
|
||||
RoleView(
|
||||
@@ -168,4 +164,27 @@ def create_app(test_config=None):
|
||||
def hello():
|
||||
return render_template_string("pong")
|
||||
|
||||
@app.route("/files/<filename>")
|
||||
def uploaded_files(filename):
|
||||
path = app.config["UPLOADED_PATH"]
|
||||
return send_from_directory(path, filename)
|
||||
|
||||
@app.route("/upload", methods=["POST"])
|
||||
def upload():
|
||||
f = request.files.get("upload")
|
||||
extension = f.filename.split(".")[-1].lower()
|
||||
if extension not in ["jpg", "gif", "png", "jpeg"]:
|
||||
return upload_fail(message="Image only!")
|
||||
f.save(os.path.join(app.config["UPLOADED_PATH"], f.filename))
|
||||
url = url_for("uploaded_files", filename=f.filename)
|
||||
return upload_success(url=url)
|
||||
|
||||
@app.route("/favicon.ico")
|
||||
def favicon():
|
||||
return send_from_directory(
|
||||
os.path.join(app.root_path, "static"),
|
||||
"favicon.ico",
|
||||
mimetype="image/vnd.microsoft.icon",
|
||||
)
|
||||
|
||||
return app
|
||||
|
@@ -1,29 +1,35 @@
|
||||
import locale
|
||||
import re
|
||||
|
||||
from flask import (abort, current_app, redirect, render_template, request,
|
||||
session, url_for)
|
||||
from flask import abort, current_app, render_template
|
||||
|
||||
from ..dbase.database import (get_all_posts_by_tag, get_page,
|
||||
get_paginated_posts, get_post, get_tags)
|
||||
from ..dbase.database import (
|
||||
get_all_posts_by_tag,
|
||||
get_page,
|
||||
get_paginated_posts,
|
||||
get_post,
|
||||
get_tags,
|
||||
)
|
||||
from .blog import bp
|
||||
|
||||
locale.setlocale(locale.LC_ALL, "")
|
||||
locale.setlocale(locale.LC_ALL, ("ru", "utf-8"))
|
||||
|
||||
|
||||
@bp.route("/", methods=["GET"], defaults={"page": 1})
|
||||
@bp.route("/")
|
||||
@bp.route("/<int:page>")
|
||||
def index(page=1):
|
||||
session["back_url"] = request.url
|
||||
per_page = current_app.config.get("POSTS_ON_PAGE")
|
||||
|
||||
posts, total_pages = get_paginated_posts(page, per_page)
|
||||
posts, total = get_paginated_posts(page, per_page)
|
||||
total_pages = total // per_page + [0, 1][total % per_page != 0]
|
||||
|
||||
list_pages = [
|
||||
x for x in range(1, total_pages + 1) if x >= page - 2 and x <= page + 2
|
||||
]
|
||||
return render_template(
|
||||
"blog/index.html",
|
||||
title=f'{current_app.config.get("BRAND")} - разговоры про питон',
|
||||
header_description="Про изучение python, веб разработку и прочие вещи",
|
||||
headers=current_app.config.get("SITE_HEADERS"),
|
||||
menu_title=current_app.config.get("BRAND"),
|
||||
menu_items=current_app.config.get("MENU_ITEMS"),
|
||||
@@ -72,6 +78,7 @@ def get_all_tags():
|
||||
return render_template(
|
||||
"blog/tags.html",
|
||||
title=f'{current_app.config.get("BRAND")} - поиск по тэгу',
|
||||
header_description="Выбор статей по тематике",
|
||||
headers=current_app.config.get("SITE_HEADERS"),
|
||||
menu_title=current_app.config.get("BRAND"),
|
||||
tags=tags,
|
||||
@@ -81,32 +88,30 @@ def get_all_tags():
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/tag/", methods=["GET"], defaults={"page": 1})
|
||||
@bp.route("/tag/<path:tag>")
|
||||
@bp.route("/tag/")
|
||||
@bp.route("/tag/<path:tag>/<int:page>")
|
||||
def get_posts_by_tag(page=1, tag=None):
|
||||
if tag is None:
|
||||
tag = request.args.get("tag")
|
||||
if tag is None:
|
||||
return redirect(url_for(".get_all_tags"))
|
||||
|
||||
per_page = current_app.config.get("POSTS_ON_PAGE")
|
||||
posts, total = get_all_posts_by_tag(tag, page, per_page)
|
||||
total_pages = total // per_page + [0, 1][total % per_page != 0]
|
||||
|
||||
if posts is None:
|
||||
abort(404)
|
||||
|
||||
total_pages = total // per_page + [0, 1][total % per_page != 0]
|
||||
|
||||
list_pages = [
|
||||
x for x in range(1, total_pages + 1) if x >= page - 2 and x <= page + 2
|
||||
]
|
||||
|
||||
return render_template(
|
||||
"blog/index.html",
|
||||
"blog/tagget_posts.html",
|
||||
title=f'{current_app.config.get("BRAND")} - посты по {tag}',
|
||||
header_description=f"Статьи по теме {tag}",
|
||||
headers=current_app.config.get("SITE_HEADERS"),
|
||||
menu_title=current_app.config.get("BRAND"),
|
||||
menu_items=current_app.config.get("MENU_ITEMS"),
|
||||
posts=posts,
|
||||
page=page,
|
||||
tag=tag,
|
||||
total_pages=total_pages,
|
||||
list_pages=list_pages,
|
||||
mylinks=current_app.config.get("MYLINKS"),
|
||||
@@ -122,6 +127,7 @@ def page(slug=None):
|
||||
return render_template(
|
||||
"blog/page.html",
|
||||
title=f'{current_app.config.get("BRAND")} - {page.name}',
|
||||
header_description=page.header_description,
|
||||
headers=current_app.config.get("SITE_HEADERS"),
|
||||
menu_title=current_app.config.get("BRAND"),
|
||||
menu_items=current_app.config.get("MENU_ITEMS"),
|
||||
|
103
pyproger/config.py
Executable file → Normal file
103
pyproger/config.py
Executable file → Normal file
@@ -1,46 +1,81 @@
|
||||
import os
|
||||
|
||||
# Настройки блога
|
||||
MYLIPOSTS_ON_PAGE = 6
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
# Тема оформления админ панели
|
||||
FLASK_ADMIN_SWATCH = "slate"
|
||||
|
||||
# Тестовый ключ
|
||||
SECRET_KEY = "Test_secret_key"
|
||||
class Settings(BaseSettings):
|
||||
# app settings
|
||||
MODE: str
|
||||
|
||||
SQLALCHEMY_ECHO = False
|
||||
BRAND: str
|
||||
COPYRIGHT_YEAR: int
|
||||
COPYRIGHT_NAME: str
|
||||
COPYRIGHT_LINK: str
|
||||
COPYRIGHT_CITY: str
|
||||
POSTS_ON_PAGE: int = 6
|
||||
|
||||
# Настройки Flask-Security
|
||||
SECURITY_URL_PREFIX = "/admin"
|
||||
SECURITY_PASSWORD_HASH = "pbkdf2_sha512"
|
||||
SECURITY_PASSWORD_SALT = "Password_salt"
|
||||
SECURITY_TRACKABLE = True
|
||||
# sqlalchemy cofiguration
|
||||
DB_HOST: str
|
||||
DB_PORT: int
|
||||
DB_USER: str
|
||||
DB_PASS: str
|
||||
DB_NAME: str
|
||||
SQLALCHEMY_ECHO: bool = False
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS: bool = False
|
||||
|
||||
SECURITY_LOGIN_URL = "/login/"
|
||||
SECURITY_LOGOUT_URL = "/logout/"
|
||||
SECURITY_REGISTER_URL = "/register/"
|
||||
# Flask config
|
||||
SECRET_KEY: str
|
||||
|
||||
SECURITY_POST_LOGIN_VIEW = "/admin/"
|
||||
SECURITY_POST_LOGOUT_VIEW = "/admin/"
|
||||
SECURITY_POST_REGISTER_VIEW = "/admin/"
|
||||
SECURITY_POST_RESET_VIEW = "/admin/"
|
||||
# Flask-Admin config
|
||||
FLASK_ADMIN_SWATCH: str = "slate"
|
||||
|
||||
SECURITY_REGISTERABLE = False
|
||||
SECURITY_CHANGEABLE = True
|
||||
SECURITY_RECOVERABLE = False
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
# Flask-Security-two config
|
||||
SECURITY_PASSWORD_SALT: str
|
||||
SECURITY_URL_PREFIX: str = "/admin"
|
||||
SECURITY_PASSWORD_HASH: str = "pbkdf2_sha512"
|
||||
SECURITY_TRACKABLE: bool = True
|
||||
|
||||
SECURITY_LOGIN_URL: str = "/login/"
|
||||
SECURITY_LOGOUT_URL: str = "/logout/"
|
||||
SECURITY_REGISTER_URL: str = "/register/"
|
||||
|
||||
SECURITY_POST_LOGIN_VIEW: str = "/admin/"
|
||||
SECURITY_POST_LOGOUT_VIEW: str = "/admin/"
|
||||
SECURITY_POST_REGISTER_VIEW: str = "/admin/"
|
||||
SECURITY_POST_RESET_VIEW: str = "/admin/"
|
||||
|
||||
SECURITY_REGISTERABLE: bool = False
|
||||
SECURITY_CHANGEABLE: bool = True
|
||||
SECURITY_RECOVERABLE: bool = False
|
||||
|
||||
SECURITY_SEND_REGISTER_EMAIL: bool = False
|
||||
SECURITY_SEND_PASSWORD_CHANGE_EMAIL: bool = False
|
||||
SECURITY_SEND_PASSWORD_RESET_EMAIL: bool = False
|
||||
SECURITY_SEND_PASSWORD_RESET_NOTICE_EMAIL: bool = False
|
||||
|
||||
# Настройки Flask-Babel необходимые для русификации админки
|
||||
LANGUAGES: list = ["ru"]
|
||||
BABEL_TRANSLATION_DIRECTORIES: str = os.path.join(os.path.curdir, "translations")
|
||||
|
||||
# Flask-ckeditor config
|
||||
basedir: str = os.path.abspath(os.path.dirname(__file__))
|
||||
CKEDITOR_PKG_TYPE: str = "full"
|
||||
CKEDITOR_SERVE_LOCAL: bool = True
|
||||
CKEDITOR_ENABLE_CODESNIPPET: bool = True
|
||||
CKEDITOR_CODE_THEME: str = "monokai_sublime"
|
||||
CKEDITOR_FILE_UPLOADER: str = "upload"
|
||||
# app.config['CKEDITOR_ENABLE_CSRF'] = True # if you want to enable CSRF protect, uncomment this line
|
||||
UPLOADED_PATH: str = os.path.join(basedir, "uploads")
|
||||
|
||||
@property
|
||||
def DB_URL(self):
|
||||
return f"postgresql+psycopg2://{self.DB_USER}:{self.DB_PASS}@{self.DB_HOST}:{self.DB_PORT}/{self.DB_NAME}"
|
||||
|
||||
model_config = SettingsConfigDict(env_file=".env")
|
||||
|
||||
|
||||
|
||||
settings = Settings()
|
||||
|
||||
SECURITY_SEND_REGISTER_EMAIL = False
|
||||
SECURITY_SEND_PASSWORD_CHANGE_EMAIL = False
|
||||
SECURITY_SEND_PASSWORD_RESET_EMAIL = False
|
||||
SECURITY_SEND_PASSWORD_RESET_NOTICE_EMAIL = False
|
||||
|
||||
# Настройки Flask-Babel необходимые для русификации админки
|
||||
LANGUAGES = ["ru"]
|
||||
BABEL_TRANSLATION_DIRECTORIES = os.path.join(os.path.curdir, "translations")
|
||||
|
||||
CKEDITOR_PKG_TYPE = "full"
|
||||
CKEDITOR_SERVE_LOCAL = True
|
||||
CKEDITOR_ENABLE_CODESNIPPET = True
|
||||
CKEDITOR_CODE_THEME = "monokai_sublime"
|
||||
|
@@ -6,7 +6,8 @@ def get_paginated_posts(page, per_page):
|
||||
all_post_query = (
|
||||
db.session.query(Post, User)
|
||||
.join(User, Post.author == User.id)
|
||||
.order_by(Post.create_datetime.desc())
|
||||
.filter(Post.published.is_(True))
|
||||
.order_by(Post.update_datetime.desc())
|
||||
.paginate(page=page, per_page=per_page, error_out=True)
|
||||
)
|
||||
return all_post_query, all_post_query.total
|
||||
@@ -16,6 +17,7 @@ def get_post(slug):
|
||||
post_query = (
|
||||
db.session.query(Post, User)
|
||||
.join(User, Post.author == User.id)
|
||||
.filter(Post.published.is_(True))
|
||||
.filter(Post.slug == slug)
|
||||
.first()
|
||||
)
|
||||
@@ -31,16 +33,14 @@ def get_all_posts_by_tag(tag, page, per_page):
|
||||
posts_query = (
|
||||
db.session.query(Post, User)
|
||||
.join(User, Post.author == User.id)
|
||||
.filter(Post.published.is_(True))
|
||||
.filter(Post.tags.any(Tag.tag == tag))
|
||||
.order_by(Post.create_datetime.desc())
|
||||
.order_by(Post.update_datetime.desc())
|
||||
.paginate(page=page, per_page=per_page, error_out=True)
|
||||
)
|
||||
total_pages = (
|
||||
posts_query.total // per_page + [0, 1][posts_query.total % per_page != 0]
|
||||
)
|
||||
if posts_query.total == 0:
|
||||
return None, None
|
||||
return posts_query, total_pages
|
||||
return None, False
|
||||
return posts_query, posts_query.total
|
||||
|
||||
|
||||
def get_page(slug):
|
||||
|
@@ -1,5 +1,3 @@
|
||||
import datetime
|
||||
|
||||
from flask_security.models import fsqla
|
||||
from sqlalchemy import Boolean, Column, DateTime, Integer, String, Text
|
||||
from sqlalchemy.sql import func
|
||||
@@ -72,6 +70,7 @@ class Post(db.Model):
|
||||
author = Column(Integer, db.ForeignKey("user.id"))
|
||||
slug = Column(String(100), nullable=False)
|
||||
title = Column(Text, nullable=False)
|
||||
header_description = Column(Text)
|
||||
description = Column(Text, nullable=False)
|
||||
published = Column(Boolean, default=False)
|
||||
tags = db.relationship("Tag", secondary=tag_post)
|
||||
@@ -99,6 +98,7 @@ class Page(db.Model):
|
||||
unique=True,
|
||||
autoincrement=True,
|
||||
)
|
||||
header_description = Column(Text)
|
||||
name = Column(String(20))
|
||||
slug = Column(String(50), nullable=False)
|
||||
text = Column(Text)
|
||||
|
0
pyproger/errors/__init__.py
Executable file → Normal file
0
pyproger/errors/__init__.py
Executable file → Normal file
0
pyproger/errors/errors.py
Executable file → Normal file
0
pyproger/errors/errors.py
Executable file → Normal file
0
pyproger/errors/routes.py
Executable file → Normal file
0
pyproger/errors/routes.py
Executable file → Normal file
@@ -1,5 +1,4 @@
|
||||
from flask import make_response, render_template
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
from pyproger.dbase.database import get_posts_for_sitemap
|
||||
|
||||
|
BIN
pyproger/static/favicon.ico
Normal file
BIN
pyproger/static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
@@ -1,6 +1,14 @@
|
||||
{% extends 'admin/model/edit.html' %}
|
||||
|
||||
{% block head %}
|
||||
{{ super()}}
|
||||
{{ ckeditor.load_code_theme() }}
|
||||
{% endblock head %}
|
||||
|
||||
{% block tail %}
|
||||
{{ super() }}
|
||||
{{ ckeditor.load() }}
|
||||
{% endblock %}
|
||||
{{ ckeditor.config(name='title')}}
|
||||
{{ ckeditor.config(name='description')}}
|
||||
{{ ckeditor.config(name='text', height=700)}}
|
||||
{% endblock tail %}
|
||||
|
0
pyproger/templates/admin/index.html
Executable file → Normal file
0
pyproger/templates/admin/index.html
Executable file → Normal file
@@ -6,6 +6,8 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
<title>{% block title %}{% endblock title %}</title>
|
||||
<meta name="description" content="{% block header_description %}{% endblock header_description %}" />
|
||||
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
|
||||
{% for h in headers %}
|
||||
{{h.content | safe}}
|
||||
{% endfor %}
|
||||
@@ -36,17 +38,17 @@
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="text-body navbar-nav me-auto mb-2 mb-lg-0 p-3">
|
||||
<li>
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white"
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white p-2 link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-75-hover"
|
||||
href="{{ url_for('bp_blog.index')}}">Главная
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white"
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white p-2 link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-75-hover"
|
||||
href="{{ url_for('bp_blog.get_all_tags')}}">Статьи по темам</a>
|
||||
</li>
|
||||
{% for m in menu_items %}
|
||||
<li>
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white"
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white p-2 link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-75-hover"
|
||||
href="/{{m.slug}}">{{m.name}}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
@@ -78,27 +80,27 @@
|
||||
<!-- Section: Social media -->
|
||||
|
||||
<!-- Section: Links -->
|
||||
<section class="">
|
||||
<section class="container-fluid justify-content-center">
|
||||
<!--Grid row-->
|
||||
<div class="row">
|
||||
<!--Grid column-->
|
||||
<div class="col-lg-3 col-md-6 mb-4 mb-md-0">
|
||||
<div class="col-lg-6 col-md-6 mb-4 mb-md-0">
|
||||
<h5 class="text-white">{{ menu_title }}.ru</h5>
|
||||
|
||||
<ul class="list-unstyled mb-0">
|
||||
<li>
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white"
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-75-hover"
|
||||
href="{{ url_for('bp_blog.index')}}">Главная
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white"
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-75-hover"
|
||||
href="{{ url_for('bp_blog.get_all_tags')}}">Статьи по темам</a>
|
||||
</li>
|
||||
|
||||
{% for m in menu_items %}
|
||||
<li>
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white"
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-75-hover"
|
||||
href="/{{m.slug}}">{{m.name}}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
@@ -107,24 +109,24 @@
|
||||
<!--Grid column-->
|
||||
|
||||
<!--Grid column-->
|
||||
<div class="col-lg-3 col-md-6 mb-4 mb-md-0">
|
||||
<div class="col-lg-6 col-md-6 mb-4 mb-md-0">
|
||||
<h5 class="text-white">Вебхостинг</h5>
|
||||
|
||||
<ul class="list-unstyled mb-0">
|
||||
<li>
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white"
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-75-hover"
|
||||
href="https://www.reg.ru/?rlink=reflink-11750021">Российский регистратор reg.ru </a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white"
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-75-hover"
|
||||
href="https://www.reg.ru/domain/new/?rlink=reflink-11750021">Регистрация доменов</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white"
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-75-hover"
|
||||
href="https://www.reg.ru/hosting/?rlink=reflink-11750021">Веб хостинг сайтов</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white"
|
||||
<a class="link-offset-2 link-underline link-underline-opacity-0 text-white link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-75-hover"
|
||||
href="https://www.reg.ru/vps/cloud/?rlink=reflink-11750021">Облачные серверы</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
@@ -4,6 +4,10 @@
|
||||
{{title}}
|
||||
{% endblock %}
|
||||
|
||||
{% block header_description %}
|
||||
{{ header_description }}
|
||||
{% endblock %}
|
||||
|
||||
{% block menu_title %}
|
||||
{{ menu_title }}
|
||||
{% endblock %}
|
||||
@@ -18,7 +22,7 @@
|
||||
</a>
|
||||
<small>
|
||||
{% for t in p.Post.tags %}
|
||||
<a class="link-offset-2 link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="{{url_for(".get_posts_by_tag", tag=t.tag )}}">
|
||||
<a class="link-offset-2 link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/tag/{{t.tag}}/1">
|
||||
#{{t.tag}}
|
||||
</a>
|
||||
{% endfor %}<br>
|
||||
@@ -33,25 +37,27 @@
|
||||
|
||||
<nav class="container p-3">
|
||||
<ul class="pagination justify-content-center"
|
||||
{% block nav_pages %}
|
||||
{% if posts.has_prev %}
|
||||
<li class="page-item"><a class="page-link" href="{{ url_for(".index", page=posts.prev_num)}}"><<</a></li>
|
||||
<li class="page-item"><a class="page-link" href="/1"><<</a></li>
|
||||
{% else %}
|
||||
<li class="page-item disabled"><a class="page-link" ><<</a></li>
|
||||
{% endif %}
|
||||
|
||||
{% for i in list_pages %}
|
||||
{% if i == page %}
|
||||
<li class="page-item active"><a class="page-link" href="{{ url_for(".index", page=i)}}">{{ i }}</a></li>
|
||||
<li class="page-item active"><a class="page-link" href="/{{i}}">{{ i }}</a></li>
|
||||
{% else %}
|
||||
<li class="page-item"><a class="page-link" href="{{ url_for(".index", page=i)}}">{{ i }}</a></li>
|
||||
<li class="page-item"><a class="page-link" href="/{{i}}">{{ i }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if posts.has_next %}
|
||||
<li class="page-item"><a class="page-link" href="{{ url_for(".index", page=posts.next_num)}}">>></a></li>
|
||||
<li class="page-item"><a class="page-link" href="/{{total_pages}}">>></a></li>
|
||||
{% else %}
|
||||
<li class="page-item disabled"><a class="page-link" >>></a></li>
|
||||
{% endif %}
|
||||
{% endblock nav_pages %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endblock %}
|
||||
|
@@ -8,6 +8,10 @@
|
||||
{{ menu_title }}
|
||||
{% endblock %}
|
||||
|
||||
{% block header_description %}
|
||||
{{ header_description }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Main Content-->
|
||||
<div class="conteiner ">
|
||||
|
@@ -4,12 +4,16 @@
|
||||
{{ title }}
|
||||
{% endblock %}
|
||||
|
||||
{% block header_description%}
|
||||
{{ post.Post.header_description }}
|
||||
{% endblock%}
|
||||
|
||||
{% block menu_title %}
|
||||
{{ menu_title }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="conteiner p-4 px-lg-5">
|
||||
<div class="container p-4 px-lg-5">
|
||||
<h4>{{ post.Post.title | safe }}</h4>
|
||||
{{ post.Post.text | safe }}
|
||||
</div>
|
||||
|
23
pyproger/templates/blog/tagget_posts.html
Normal file
23
pyproger/templates/blog/tagget_posts.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{% extends 'blog/index.html' %}
|
||||
|
||||
{% block nav_pages %}
|
||||
{% if posts.has_prev %}
|
||||
<li class="page-item"><a class="page-link" href="/tag/{{tag}}/1"><<</a></li>
|
||||
{% else %}
|
||||
<li class="page-item disabled"><a class="page-link"><<</a></li>
|
||||
{% endif %}
|
||||
|
||||
{% for i in list_pages %}
|
||||
{% if i == page %}
|
||||
<li class="page-item active"><a class="page-link" href="/tag/{{tag}}/{{i}}">{{ i }}</a></li>
|
||||
{% else %}
|
||||
<li class="page-item"><a class="page-link" href="/tag/{{tag}}/{{i}}">{{ i }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if posts.has_next %}
|
||||
<li class="page-item"><a class="page-link" href="/tag/{{tag}}/{{total_pages}}">>></a></li>
|
||||
{% else %}
|
||||
<li class="page-item disabled"><a class="page-link">>></a></li>
|
||||
{% endif %}
|
||||
{% endblock nav_pages %}
|
@@ -4,6 +4,10 @@
|
||||
{{title}}
|
||||
{% endblock %}
|
||||
|
||||
{% block header_description %}
|
||||
{{ header_description }}
|
||||
{% endblock %}
|
||||
|
||||
{% block menu_title %}
|
||||
{{ menu_title }}
|
||||
{% endblock %}
|
||||
@@ -15,7 +19,7 @@
|
||||
<h4>Тэги статей:</h4>
|
||||
{% for t in tags %}
|
||||
<li>
|
||||
<a class="link-offset-2 link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="{{url_for(".get_posts_by_tag", tag=t.tag )}}">
|
||||
<a class="link-offset-2 link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/tag/{{t.tag}}/1">
|
||||
#{{t.tag}}
|
||||
</a>
|
||||
</li>
|
||||
|
0
pyproger/templates/errors/404.html
Executable file → Normal file
0
pyproger/templates/errors/404.html
Executable file → Normal file
0
pyproger/templates/my_master.html
Executable file → Normal file
0
pyproger/templates/my_master.html
Executable file → Normal file
@@ -5,6 +5,7 @@ Disallow: /static/
|
||||
Disallow: /post/$
|
||||
Disallow: /tag/
|
||||
Disallow: /tags/
|
||||
Allow: /post/*
|
||||
Allow: /static/*.css
|
||||
Allow: /static/*.js
|
||||
Allow: /static/*.png
|
||||
@@ -18,6 +19,7 @@ Disallow: /static/
|
||||
Disallow: /post/$
|
||||
Disallow: /tag/
|
||||
Disallow: /tags/
|
||||
Allow: /post/*
|
||||
Allow: /static/*.css
|
||||
Allow: /static/*.js
|
||||
Allow: /static/*.png
|
||||
@@ -31,6 +33,7 @@ Disallow: /static/
|
||||
Disallow: /post/$
|
||||
Disallow: /tag/
|
||||
Disallow: /tags/
|
||||
Allow: /post/*
|
||||
Crawl-Delay: 5
|
||||
|
||||
Sitemap: https://pyproger.ru/sitemap.xml
|
||||
|
0
pyproger/templates/security/_macros.html
Executable file → Normal file
0
pyproger/templates/security/_macros.html
Executable file → Normal file
0
pyproger/templates/security/change_password.html
Executable file → Normal file
0
pyproger/templates/security/change_password.html
Executable file → Normal file
0
pyproger/templates/security/forgot_password.html
Executable file → Normal file
0
pyproger/templates/security/forgot_password.html
Executable file → Normal file
0
pyproger/templates/security/login_user.html
Executable file → Normal file
0
pyproger/templates/security/login_user.html
Executable file → Normal file
0
pyproger/templates/security/register_user.html
Executable file → Normal file
0
pyproger/templates/security/register_user.html
Executable file → Normal file
0
pyproger/templates/security/reset_password.html
Executable file → Normal file
0
pyproger/templates/security/reset_password.html
Executable file → Normal file
@@ -1,5 +1,3 @@
|
||||
import os
|
||||
|
||||
from flask import Blueprint, current_app, request
|
||||
from flask_babel import Babel
|
||||
|
||||
|
0
pyproger/uploads/.gitkeep
Normal file
0
pyproger/uploads/.gitkeep
Normal file
@@ -6,7 +6,7 @@ authors = ["Sergey Vanyushkin <pi3c@yandex.ru>"]
|
||||
readme = "README.md"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.11"
|
||||
python = "^3.10"
|
||||
flask = "^2.3.3"
|
||||
gunicorn = "^21.2.0"
|
||||
sqlalchemy = "^2.0.20"
|
||||
@@ -14,12 +14,14 @@ flask-sqlalchemy = "^3.1.1"
|
||||
flask-security-too = "^5.3.0"
|
||||
flask-migrate = "^4.0.5"
|
||||
flask-admin = "^1.6.1"
|
||||
psycopg2 = "^2.9.7"
|
||||
click = "^8.1.7"
|
||||
flask-ckeditor = "^0.4.6"
|
||||
flask-babel = "^3.1.0"
|
||||
python-dotenv = "^1.0.0"
|
||||
werkzeug = "2.3.7"
|
||||
psycopg2-binary = "^2.9.9"
|
||||
pydantic = "^2.5.3"
|
||||
pydantic-settings = "^2.1.0"
|
||||
|
||||
|
||||
[build-system]
|
||||
|
5
pytest.ini
Normal file
5
pytest.ini
Normal file
@@ -0,0 +1,5 @@
|
||||
[pytest]
|
||||
# env_override_existing_values = 1
|
||||
pythonpath = . pyproger
|
||||
env_files =
|
||||
.test.env
|
0
tests/conftest.py
Normal file
0
tests/conftest.py
Normal file
Reference in New Issue
Block a user