добавил краткое описание и форматирование в заголовок, описание и текст статьи

main
Сергей Ванюшкин 2023-09-22 14:31:42 +03:00
parent 23e8a2e492
commit 7c6fc02529
13 changed files with 237 additions and 10 deletions

View File

@ -1,8 +1,8 @@
"""initial_migration
Revision ID: af05a1cbd975
Revision ID: 8c415e462cb3
Revises:
Create Date: 2023-09-19 22:57:11.510132
Create Date: 2023-09-22 12:19:22.923813
"""
import flask_security
@ -10,7 +10,7 @@ import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = "af05a1cbd975"
revision = "8c415e462cb3"
down_revision = None
branch_labels = None
depends_on = None
@ -20,8 +20,8 @@ def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"role",
sa.Column("id", sa.Integer(), nullable=False),
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(
@ -78,8 +78,9 @@ def upgrade():
"post",
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
sa.Column("author", sa.Integer(), nullable=True),
sa.Column("slug", sa.String(length=30), nullable=False),
sa.Column("title", sa.String(length=50), nullable=False),
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),

View File

@ -1,4 +1,4 @@
from flask import abort, redirect, request, url_for
from flask import abort, g, redirect, request, url_for
from flask_admin.contrib import sqla
from flask_ckeditor import CKEditorField
from flask_security import current_user
@ -72,6 +72,7 @@ class PostView(MyAdminView):
tags="Тэги",
slug="Слаг",
title="Заголовок",
description="Краткое описание статьи",
author="Автор",
published="Опубликовано",
create_datetime="Дата создания",
@ -79,6 +80,10 @@ class PostView(MyAdminView):
text="Текст",
)
form_overrides = dict(text=CKEditorField)
form_overrides = dict(
title=CKEditorField,
description=CKEditorField,
text=CKEditorField,
)
create_template = "admin/edit.html"
edit_template = "admin/edit.html"

View File

@ -76,6 +76,10 @@ def create_app(test_config=None):
app.register_blueprint(bp_cli)
from pyproger.blog.blog import bp as bp_blog
app.register_blueprint(bp_blog)
@security.context_processor
def security_context_processor():
return dict(

View File

9
pyproger/blog/blog.py Normal file
View File

@ -0,0 +1,9 @@
from flask import Blueprint
bp = Blueprint(
"bp_blog",
__name__,
template_folder="templates/blog",
)
from . import urls

43
pyproger/blog/urls.py Normal file
View File

@ -0,0 +1,43 @@
import locale
from flask import render_template, render_template_string, request
from ..dbase.database import get_paginated_posts, get_post
from .blog import bp
locale.setlocale(locale.LC_ALL, "")
@bp.route("/", methods=["GET"], defaults={"page": 1})
@bp.route("/<int:page>", methods=["GET"])
def index(page=1):
per_page = 3
posts, total_pages = get_paginated_posts(page, per_page)
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",
request=request,
posts=posts,
title="pyproger - разговоры про питон",
menu_title="pyproger",
page=page,
total_pages=total_pages,
list_pages=list_pages,
)
@bp.route("/post/")
@bp.route("/post/<path:slug>")
def post(slug=None):
if slug:
current_post = get_post(slug)
return render_template(
"blog/postview.html",
title=f"pyproger - {current_post.Post.title}",
menu_title="pyproger",
post=current_post,
)
else:
return render_template_string("noup")

View File

@ -0,0 +1,24 @@
from . import db
from .models import Post, User
def get_paginated_posts(page, per_page):
quer = (
db.session.query(Post, User)
.join(User, Post.author == User.id)
.order_by(Post.create_datetime.desc())
.paginate(page=page, per_page=per_page, error_out=False)
)
total_pages = quer.total // per_page + [0, 1][quer.total % per_page != 0]
return quer, total_pages
def get_post(slug):
post_query = (
db.session.query(Post, User)
.join(User, Post.author == User.id)
.filter(Post.slug == slug)
.first()
)
return post_query

View File

@ -1,5 +1,6 @@
import datetime
from flask_security import current_user
from flask_security.models import fsqla
from sqlalchemy import Boolean, Column, DateTime, Integer, String, Text
@ -69,8 +70,9 @@ class Post(db.Model):
autoincrement=True,
)
author = Column(Integer, db.ForeignKey("user.id"))
slug = Column(String(30), nullable=False)
title = Column(String(50), nullable=False)
slug = Column(String(100), nullable=False)
title = Column(Text, nullable=False)
description = Column(Text, nullable=False)
published = Column(Boolean, default=False)
tags = db.relationship("Tag", secondary=tag_post)
@ -82,5 +84,6 @@ class Post(db.Model):
update_datetime = Column(
DateTime(),
nullable=True,
onupdate=datetime.datetime.utcnow(),
)
text = Column(Text)

View File

@ -8,5 +8,7 @@ if you have set the configuration variables more than CKEDITOR_SERVE_LOCAL and C
or you need to config the CKEditor textarea, use the line below to register the configuration.
The name value should be the name of the CKEditor form field.
#}
{{ ckeditor.config(name='Title') }}
{{ ckeditor.config(name='Text') }}
{% endblock %}

View File

@ -0,0 +1,50 @@
<!doctype html>
<html lang="{{page_lang}}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>
{% block title %}
{% endblock title %}
</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
<body>
<div id="main-container" class="container-fluid">
<nav class="navbar p-2 navbar-expand-lg bg-dark border-bottom border-bottom-dark rounded-bottom-4"
data-bs-theme="dark">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for(".index")}}">
{% block menu_title %}
{% endblock menu_title %}</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Переключатель навигации">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
text
</ul>
</div>
</div>
</nav>
<div id="content-container" class="container-fluid">
{% block content %} {% endblock %}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz"
crossorigin="anonymous"></script>
</body>
</html>

View File

@ -0,0 +1,58 @@
{% extends 'blog/base.html' %}
{% block title %}
{{title}}
{% endblock %}
{% block menu_title %}
{{ menu_title }}
{% endblock %}
{% block content %}
<div class="conteiner">
<br>
</div>
<div class="container px-4 px-lg-5">
<div class="list-group justify-content-center">
{% for p in posts %}
<a href="{{ url_for(".post", slug=p.Post.slug )}}" class="list-group-item list-group-item-action border-0">
<h5 class="post-title">{{ p.Post.title | safe }}</h5>
{{ p.Post.description | safe}}
</a>
<small>
Опубликовал
<a href="mailto:{{p.User.email}}">
{{ p.User.username}}
</a>
{{ p.Post.create_datetime.strftime('%d %B, %Y') }}
</small>
<hr class="my-4" />
{% endfor %}
</div>
<nav class="container">
<ul class="pagination justify-content-start"
{% if posts.has_prev %}
<li class="page-item"><a class="page-link" href="{{ url_for(".index", page=posts.prev_num)}}">&lt;&lt;</a></li>
{% else %}
<li class="page-item disabled"><a class="page-link" >&lt;&lt;</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>
{% else %}
<li class="page-item"><a class="page-link" href="{{ url_for(".index", page=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)}}">&gt;&gt;</a></li>
{% else %}
<li class="page-item disabled"><a class="page-link" >&gt;&gt;</a></li>
{% endif %}
</nav>
{% endblock %}

View File

@ -0,0 +1,19 @@
{% extends 'blog/base.html' %}
{% block title %}
{{title}}
{% endblock %}
{% block menu_title %}
{{ menu_title }}
{% endblock %}
{% block content %}
<!-- Main Content-->
<div class="conteiner">
<br>
<h4>{{ post.Post.title | safe }}</h4>
{{ post.Post.text | safe }}
</div>
{% endblock %}

View File

@ -0,0 +1,9 @@
<html>
<body>
<div>
<a href="{{ url_for('admin.index') }}">админ панель</a>
</div>
</body>
</html>