From 199eb0f3ae056ba0d8c27fbf79ae4b2a41d0f042 Mon Sep 17 00:00:00 2001 From: pi3c Date: Tue, 10 Oct 2023 22:44:32 +0300 Subject: [PATCH] refactoring --- generate_dotenv.py | 34 ++++- migrations/script.py.mako | 1 + migrations/versions/5e6d181b4b74_.py | 34 ----- .../68537cc1688c_initial_migration.py | 126 +++++++++++++++++ .../8c415e462cb3_initial_migration.py | 132 ------------------ migrations/versions/e24055e16b26_.py | 42 ------ migrations/versions/ea0fde3014d7_.py | 36 ----- pyproger/admin/views.py | 9 ++ pyproger/app.py | 42 +++++- pyproger/config.py | 15 +- pyproger/dbase/database.py | 10 +- pyproger/dbase/models.py | 14 ++ pyproger/templates/blog/base.html | 2 +- 13 files changed, 230 insertions(+), 267 deletions(-) delete mode 100644 migrations/versions/5e6d181b4b74_.py create mode 100644 migrations/versions/68537cc1688c_initial_migration.py delete mode 100644 migrations/versions/8c415e462cb3_initial_migration.py delete mode 100644 migrations/versions/e24055e16b26_.py delete mode 100644 migrations/versions/ea0fde3014d7_.py diff --git a/generate_dotenv.py b/generate_dotenv.py index 61c49f1..07a5ff2 100644 --- a/generate_dotenv.py +++ b/generate_dotenv.py @@ -1,5 +1,6 @@ import os import uuid +from datetime import datetime as dt from dotenv import load_dotenv @@ -9,12 +10,16 @@ if os.path.exists(dotenv_path): with open(dotenv_path, "a") as f: + if os.getenv("BRAND") is None: + 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("SECRET_KEY уже установлен, пропускаю") print('Генерирую "Соль"...') if os.getenv("SECURITY_PASSWORD_SALT") is None: @@ -27,9 +32,32 @@ with open(dotenv_path, "a") as f: print("Настроки подключения к базе данных Posgresql:") login = input("Введите логин пользователя бд: ") passwd = input("Пароль: ") - db = input("Название бд (по умолчанию pyproger):") or "pyproger" + 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}" + f"SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://{login}:{passwd}@{ip}:{port}/{db}\n" ) + + if os.getenv("COPYRIGHT_YEAR") is None: + start_date = dt.utcnow().strftime("%Y") + f.writelines(f"COPYRIGHT_YEAR={start_date}\n") + + if os.getenv("COPYRIGHT_NAME") is None: + name = input("Введите имя для для футера:") + f.writelines(f"COPYRIGHT_NAME={name}\n") + + if os.getenv("COPYRIGHT_LINK") is None: + print("Введите ссылку для футера:") + print( + "email('something@somthing.else) или веб адрес полностью('http://anysite.any')" + ) + link = input(">:") + if link.startswith("http"): + f.writelines(f"COPYRIGHT_LINK={link}\n") + else: + f.writelines(f"COPYRIGHT_LINK=mailto:{link}\n") + + if os.getenv("COPYRIGHT_CITY") is None: + name = input("Введите свой город для для футера:") + f.writelines(f"COPYRIGHT_CITY={name}\n") diff --git a/migrations/script.py.mako b/migrations/script.py.mako index 2c01563..26f8b91 100644 --- a/migrations/script.py.mako +++ b/migrations/script.py.mako @@ -7,6 +7,7 @@ Create Date: ${create_date} """ from alembic import op import sqlalchemy as sa +import flask_security ${imports if imports else ""} # revision identifiers, used by Alembic. diff --git a/migrations/versions/5e6d181b4b74_.py b/migrations/versions/5e6d181b4b74_.py deleted file mode 100644 index 2cd7112..0000000 --- a/migrations/versions/5e6d181b4b74_.py +++ /dev/null @@ -1,34 +0,0 @@ -"""empty message - -Revision ID: 5e6d181b4b74 -Revises: e24055e16b26 -Create Date: 2023-10-04 08:46:50.473590 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '5e6d181b4b74' -down_revision = 'e24055e16b26' -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('update_datetime', sa.DateTime(), nullable=True)) - batch_op.create_unique_constraint(None, ['id']) - - # ### 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_constraint(None, type_='unique') - batch_op.drop_column('update_datetime') - - # ### end Alembic commands ### diff --git a/migrations/versions/68537cc1688c_initial_migration.py b/migrations/versions/68537cc1688c_initial_migration.py new file mode 100644 index 0000000..fcf08a2 --- /dev/null +++ b/migrations/versions/68537cc1688c_initial_migration.py @@ -0,0 +1,126 @@ +"""initial_migration + +Revision ID: 68537cc1688c +Revises: +Create Date: 2023-10-10 22:17:40.476992 + +""" +from alembic import op +import sqlalchemy as sa +import flask_security + + +# revision identifiers, used by Alembic. +revision = '68537cc1688c' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('footer_icons', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('name', sa.String(length=30), nullable=True), + sa.Column('bootstrap_ico', sa.String(length=20), nullable=True), + sa.Column('link', sa.String(length=100), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('id') + ) + op.create_table('page', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('name', sa.String(length=20), nullable=True), + sa.Column('slug', sa.String(length=50), nullable=False), + sa.Column('text', sa.Text(), nullable=True), + sa.Column('update_datetime', sa.DateTime(), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('id') + ) + op.create_table('role', + sa.Column('name', sa.String(length=80), nullable=False), + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('description', sa.String(length=255), nullable=True), + sa.Column('permissions', flask_security.datastore.AsaList(), nullable=True), + sa.Column('update_datetime', sa.DateTime(), server_default=sa.text('now()'), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('name') + ) + op.create_table('site_headers', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('name', sa.String(length=20), nullable=True), + sa.Column('description', sa.Text(), nullable=True), + sa.Column('content', sa.Text(), nullable=True), + sa.Column('enabled', sa.Boolean(), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('id') + ) + op.create_table('tag', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('tag', sa.String(length=20), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('user', + sa.Column('first_name', sa.String(length=255), nullable=True), + sa.Column('last_name', sa.String(length=255), nullable=True), + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('email', sa.String(length=255), nullable=False), + sa.Column('username', sa.String(length=255), nullable=True), + sa.Column('password', sa.String(length=255), nullable=False), + sa.Column('active', sa.Boolean(), nullable=False), + sa.Column('fs_uniquifier', sa.String(length=64), nullable=False), + sa.Column('confirmed_at', sa.DateTime(), nullable=True), + sa.Column('last_login_at', sa.DateTime(), nullable=True), + sa.Column('current_login_at', sa.DateTime(), nullable=True), + sa.Column('last_login_ip', sa.String(length=64), nullable=True), + sa.Column('current_login_ip', sa.String(length=64), nullable=True), + sa.Column('login_count', sa.Integer(), nullable=True), + sa.Column('tf_primary_method', sa.String(length=64), nullable=True), + sa.Column('tf_totp_secret', sa.String(length=255), nullable=True), + sa.Column('tf_phone_number', sa.String(length=128), nullable=True), + sa.Column('create_datetime', sa.DateTime(), server_default=sa.text('now()'), nullable=False), + sa.Column('update_datetime', sa.DateTime(), server_default=sa.text('now()'), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('email'), + sa.UniqueConstraint('fs_uniquifier') + ) + op.create_table('post', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('author', sa.Integer(), nullable=True), + sa.Column('slug', sa.String(length=100), nullable=False), + sa.Column('title', sa.Text(), nullable=False), + sa.Column('description', sa.Text(), nullable=False), + sa.Column('published', sa.Boolean(), nullable=True), + sa.Column('create_datetime', sa.DateTime(), nullable=True), + sa.Column('update_datetime', sa.DateTime(), nullable=True), + sa.Column('text', sa.Text(), nullable=True), + sa.ForeignKeyConstraint(['author'], ['user.id'], ), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('id') + ) + op.create_table('roles_users', + sa.Column('user_id', sa.Integer(), nullable=True), + sa.Column('role_id', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['role_id'], ['role.id'], ), + sa.ForeignKeyConstraint(['user_id'], ['user.id'], ) + ) + op.create_table('tag_post', + sa.Column('tag_id', sa.Integer(), nullable=True), + sa.Column('post_id', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['post_id'], ['post.id'], ), + sa.ForeignKeyConstraint(['tag_id'], ['tag.id'], ) + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('tag_post') + op.drop_table('roles_users') + op.drop_table('post') + op.drop_table('user') + op.drop_table('tag') + op.drop_table('site_headers') + op.drop_table('role') + op.drop_table('page') + op.drop_table('footer_icons') + # ### end Alembic commands ### diff --git a/migrations/versions/8c415e462cb3_initial_migration.py b/migrations/versions/8c415e462cb3_initial_migration.py deleted file mode 100644 index 17969c9..0000000 --- a/migrations/versions/8c415e462cb3_initial_migration.py +++ /dev/null @@ -1,132 +0,0 @@ -"""initial_migration - -Revision ID: 8c415e462cb3 -Revises: -Create Date: 2023-09-22 12:19:22.923813 - -""" -import flask_security -import sqlalchemy as sa -from alembic import op - -# revision identifiers, used by Alembic. -revision = "8c415e462cb3" -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table( - "role", - sa.Column("name", sa.String(length=80), nullable=False), - sa.Column("id", sa.Integer(), nullable=False), - sa.Column("description", sa.String(length=255), nullable=True), - sa.Column("permissions", flask_security.datastore.AsaList(), nullable=True), - sa.Column( - "update_datetime", - sa.DateTime(), - server_default=sa.text("now()"), - nullable=False, - ), - sa.PrimaryKeyConstraint("id"), - sa.UniqueConstraint("name"), - ) - op.create_table( - "tag", - sa.Column("id", sa.Integer(), autoincrement=True, nullable=False), - sa.Column("tag", sa.String(length=20), nullable=True), - sa.PrimaryKeyConstraint("id"), - ) - op.create_table( - "user", - sa.Column("first_name", sa.String(length=255), nullable=True), - sa.Column("last_name", sa.String(length=255), nullable=True), - sa.Column("id", sa.Integer(), nullable=False), - sa.Column("email", sa.String(length=255), nullable=False), - sa.Column("username", sa.String(length=255), nullable=True), - sa.Column("password", sa.String(length=255), nullable=False), - sa.Column("active", sa.Boolean(), nullable=False), - sa.Column("fs_uniquifier", sa.String(length=64), nullable=False), - sa.Column("confirmed_at", sa.DateTime(), nullable=True), - sa.Column("last_login_at", sa.DateTime(), nullable=True), - sa.Column("current_login_at", sa.DateTime(), nullable=True), - sa.Column("last_login_ip", sa.String(length=64), nullable=True), - sa.Column("current_login_ip", sa.String(length=64), nullable=True), - sa.Column("login_count", sa.Integer(), nullable=True), - sa.Column("tf_primary_method", sa.String(length=64), nullable=True), - sa.Column("tf_totp_secret", sa.String(length=255), nullable=True), - sa.Column("tf_phone_number", sa.String(length=128), nullable=True), - sa.Column( - "create_datetime", - sa.DateTime(), - server_default=sa.text("now()"), - nullable=False, - ), - sa.Column( - "update_datetime", - sa.DateTime(), - server_default=sa.text("now()"), - nullable=False, - ), - sa.PrimaryKeyConstraint("id"), - sa.UniqueConstraint("email"), - sa.UniqueConstraint("fs_uniquifier"), - ) - op.create_table( - "post", - sa.Column("id", sa.Integer(), autoincrement=True, nullable=False), - sa.Column("author", sa.Integer(), nullable=True), - sa.Column("slug", sa.String(length=100), nullable=False), - sa.Column("title", sa.Text(), nullable=False), - sa.Column("description", sa.Text(), nullable=False), - sa.Column("published", sa.Boolean(), nullable=True), - sa.Column("create_datetime", sa.DateTime(), nullable=True), - sa.Column("update_datetime", sa.DateTime(), nullable=True), - sa.Column("text", sa.Text(), nullable=True), - sa.ForeignKeyConstraint( - ["author"], - ["user.id"], - ), - sa.PrimaryKeyConstraint("id"), - sa.UniqueConstraint("id"), - ) - op.create_table( - "roles_users", - sa.Column("user_id", sa.Integer(), nullable=True), - sa.Column("role_id", sa.Integer(), nullable=True), - sa.ForeignKeyConstraint( - ["role_id"], - ["role.id"], - ), - sa.ForeignKeyConstraint( - ["user_id"], - ["user.id"], - ), - ) - op.create_table( - "tag_post", - sa.Column("tag_id", sa.Integer(), nullable=True), - sa.Column("post_id", sa.Integer(), nullable=True), - sa.ForeignKeyConstraint( - ["post_id"], - ["post.id"], - ), - sa.ForeignKeyConstraint( - ["tag_id"], - ["tag.id"], - ), - ) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table("tag_post") - op.drop_table("roles_users") - op.drop_table("post") - op.drop_table("user") - op.drop_table("tag") - op.drop_table("role") - # ### end Alembic commands ### diff --git a/migrations/versions/e24055e16b26_.py b/migrations/versions/e24055e16b26_.py deleted file mode 100644 index 4943b16..0000000 --- a/migrations/versions/e24055e16b26_.py +++ /dev/null @@ -1,42 +0,0 @@ -"""empty message - -Revision ID: e24055e16b26 -Revises: 8c415e462cb3 -Create Date: 2023-10-02 09:30:10.566908 - -""" -import flask_security -import sqlalchemy as sa -from alembic import op - -# revision identifiers, used by Alembic. -revision = "e24055e16b26" -down_revision = "8c415e462cb3" -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table( - "page", - sa.Column("id", sa.Integer(), autoincrement=True, nullable=False), - sa.Column("name", sa.String(length=20), nullable=True), - sa.Column("slug", sa.String(length=50), nullable=False), - sa.Column("text", sa.Text(), nullable=True), - sa.PrimaryKeyConstraint("id"), - sa.UniqueConstraint("id"), - ) - with op.batch_alter_table("post", 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("post", schema=None) as batch_op: - batch_op.drop_constraint(None, type_="unique") - - op.drop_table("page") - # ### end Alembic commands ### diff --git a/migrations/versions/ea0fde3014d7_.py b/migrations/versions/ea0fde3014d7_.py deleted file mode 100644 index 81abf41..0000000 --- a/migrations/versions/ea0fde3014d7_.py +++ /dev/null @@ -1,36 +0,0 @@ -"""empty message - -Revision ID: ea0fde3014d7 -Revises: 5e6d181b4b74 -Create Date: 2023-10-07 14:32:08.410786 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = 'ea0fde3014d7' -down_revision = '5e6d181b4b74' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('site_headers', - sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('name', sa.String(length=20), nullable=True), - sa.Column('description', sa.Text(), nullable=True), - sa.Column('content', sa.Text(), nullable=True), - sa.Column('enabled', sa.Boolean(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('id') - ) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('site_headers') - # ### end Alembic commands ### diff --git a/pyproger/admin/views.py b/pyproger/admin/views.py index c3ec0c4..d1306f4 100644 --- a/pyproger/admin/views.py +++ b/pyproger/admin/views.py @@ -112,3 +112,12 @@ class HeadersView(MyAdminView): "name", "description", ) + + +class FooterLinksView(MyAdminView): + column_labels = dict( + name="Название", + bootstrap_ico="Bootstrap код иконки", + link="Ссылка", + ) + column_list = ("name",) diff --git a/pyproger/app.py b/pyproger/app.py index 5cb81e7..33c699f 100644 --- a/pyproger/app.py +++ b/pyproger/app.py @@ -7,9 +7,12 @@ from flask_ckeditor import CKEditor 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_headers, get_menu_items -from pyproger.dbase.models import 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) def create_app(test_config=None): @@ -23,6 +26,13 @@ def create_app(test_config=None): 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["MYCOPYRIGHT"] = { + "year": os.getenv("COPYRIGHT_YEAR"), + "name": os.getenv("COPYRIGHT_NAME"), + "link": os.getenv("COPYRIGHT_LINK"), + "city": os.getenv("COPYRIGHT_CITY"), + } + app.config["BRAND"] = os.getenv("BRAND") else: app.config.from_mapping(test_config) @@ -98,6 +108,14 @@ def create_app(test_config=None): name="Включаемые в html заголовки", ) ) + admin.add_view( + FooterLinksView( + FooterContactLinks, + db.session, + category="Страницы", + name="Иконки-ссылки футера", + ) + ) from pyproger.blog.blog import bp as bp_blog from pyproger.cli.commands import bp_cli @@ -110,11 +128,27 @@ def create_app(test_config=None): app.register_blueprint(bp_robots) with app.app_context(): - site_headers = get_headers() + try: + site_headers = get_headers() + except Exception as e: + print(e) + site_headers = None app.config["SITE_HEADERS"] = site_headers - menu_items = get_menu_items() + + try: + menu_items = get_menu_items() + except Exception as e: + print(e) + menu_items = None app.config["MENU_ITEMS"] = menu_items + try: + links = get_footer_links() + except Exception as e: + print(e) + links = None + app.config["MYLINKS"] = links + @security.context_processor def security_context_processor(): return dict( diff --git a/pyproger/config.py b/pyproger/config.py index c485356..23be885 100755 --- a/pyproger/config.py +++ b/pyproger/config.py @@ -1,20 +1,7 @@ import os # Настройки блога -BRAND = "блог" -MYCOPYRIGHT = { - "year": "2023", - "name": "Иванов Иван", - "link": "http://yandex.ru", - "city": "г.Москва", -} -MYLINKS = ( - {"icon": "fab fa-telegram", "link": "https://t.me"}, - {"icon": "fab fa-vk", "link": "https://m.vk.com"}, - {"icon": "fab fa-yandex", "link": "mailto:user@yandex.ru"}, - {"icon": "fab fa-github", "link": "https://github.com"}, -) -POSTS_ON_PAGE = 6 +MYLIPOSTS_ON_PAGE = 6 # Тема оформления админ панели FLASK_ADMIN_SWATCH = "slate" diff --git a/pyproger/dbase/database.py b/pyproger/dbase/database.py index 4d84833..cc7c8d9 100644 --- a/pyproger/dbase/database.py +++ b/pyproger/dbase/database.py @@ -1,5 +1,5 @@ from . import db -from .models import Page, Post, SiteHeaders, Tag, User +from .models import FooterContactLinks, Page, Post, SiteHeaders, Tag, User def get_paginated_posts(page, per_page): @@ -72,3 +72,11 @@ def get_headers(): .all() ) return headers + + +def get_footer_links(): + links = db.session.query( + FooterContactLinks.link, + FooterContactLinks.bootstrap_ico, + ).all() + return links diff --git a/pyproger/dbase/models.py b/pyproger/dbase/models.py index c8866b7..5a2012e 100644 --- a/pyproger/dbase/models.py +++ b/pyproger/dbase/models.py @@ -122,3 +122,17 @@ class SiteHeaders(db.Model): description = Column(Text) content = Column(Text) enabled = Column(Boolean, default=False) + + +class FooterContactLinks(db.Model): + __tablename__ = "footer_icons" + id = Column( + Integer, + primary_key=True, + nullable=False, + unique=True, + autoincrement=True, + ) + name = Column(String(30)) + bootstrap_ico = Column(String(20)) + link = Column(String(100)) diff --git a/pyproger/templates/blog/base.html b/pyproger/templates/blog/base.html index 83d4aef..365178f 100644 --- a/pyproger/templates/blog/base.html +++ b/pyproger/templates/blog/base.html @@ -71,7 +71,7 @@ {% endfor %}