Flask 发布帖子分页

发布帖子

@bp.route("/post/public", methods=['GET', 'POST'])
@login_required
def public_post():
    if request.method == 'GET':
        # 获取所有模板数据
        boards = BoardModel.query.order_by(BoardModel.priority.desc()).all()
        return render_template("front/public_post.html", boards=boards)

在这里插入图片描述

校验富文本编辑器上传的图片

class UploadImageForm(BaseForm):
    image = FileField(validators=[FileAllowed(['jpg', 'jpeg', 'png'], message="图片格式不符合要求!"), FileSize(max_size=1024*1024*5, message="图片最大不能超过5M!")])

新建post目录用来存放帖子图片
在这里插入图片描述
在config配置文件中添加帖子图片地址

# 帖子图片存放路径
POST_IMAGE_SAVE_PATH = os.path.join(BASE_DIR, "media", "post")

wangedit返回图片的数据格式
在这里插入图片描述

富文本编辑器上传图片

@bp.post("/post/image/upload")
@login_required
def upload_post_image():
    form = UploadImageForm(request.files)
    if form.validate():
        image = form.image.data
        # 不要使用用户上传上来的文件名,否则容易被黑客攻击
        filename = image.filename
        # xxx.png,xx.jpeg
        _, ext = os.path.splitext(filename)
        filename = md5((g.user.email + str(time.time())).encode("utf-8")).hexdigest() + ext
        image_path = os.path.join(current_app.config['POST_IMAGE_SAVE_PATH'], filename)
        image.save(image_path)
        # {"data","code", "message"}
        return jsonify({"errno": 0, "data": [{
            "url": url_for("media.get_post_image", filename=filename),
            "alt": filename,
            "href": ""
        }]})
    else:
        message = form.messages[0]
        return restful.params_error(message=message)

为后面nginx映射做准备

@bp.route("/post/<filename>")
def get_post_image(filename):
    return send_from_directory(current_app.config['POST_IMAGE_SAVE_PATH'], filename)

在这里插入图片描述

发布帖子
在这里插入图片描述

@bp.route("/post/public", methods=['GET', 'POST'])
@login_required
def public_post():
    if request.method == 'GET':
        # 获取所有模板数据
        boards = BoardModel.query.order_by(BoardModel.priority.desc()).all()
        return render_template("front/public_post.html", boards=boards)
    else:
        form = PublicPostForm(request.form)
        if form.validate():
            title = form.title.data
            content = form.content.data
            board_id = form.board_id.data
            try:
                # get方法:接收一个id作为参数,如果找到了,那么会返回这条数据
                # 如果没有找到,那么会抛出异常
                board = BoardModel.query.get(board_id)
            except Exception as e:
                return restful.params_error(message="板块不存在!")
            post_model = PostModel(title=title, content=content, board=board, author=g.user)
            db.session.add(post_model)
            db.session.commit()
            # 返回帖子的id
            return restful.ok(data={"id": post_model.id})
        else:
            return restful.params_error(message=form.messages[0])

校验发布帖子的参数

class PublicPostForm(BaseForm):
    title = StringField(validators=[Length(min=3, max=200, message="帖子标题必须在3-200之间!")])
    content = StringField(validators=[InputRequired(message="请传入内容!")])
    board_id = IntegerField(validators=[InputRequired(message="请传入板块ID!")])

发布帖子成功后根据后端返回的帖子id 跳转到帖子详情
在这里插入图片描述

帖子详情API

@bp.get("/post/detail/<post_id>")
def post_detail(post_id):
    post_model = PostModel.query.get(post_id)
    comment_count = CommentModel.query.filter_by(post_id=post_id).count()
    context = {
        "comment_count": comment_count,
        "post": post_model
    }
    return render_template("front/post_detail.html", **context)

获得帖子详情
点击帖子传递帖子id获得详情
在这里插入图片描述

@bp.get("/post/detail/<int:post_id>")
def post_detail(post_id):
    try:
        # 根据帖子的id查询帖子信息
        post_model = PostModel.query.get(post_id)
    except:
        return '404'
    comment_count = CommentModel.query.filter_by(post_id=post_id).count()
    context = {
        "comment_count": comment_count,
        "post": post_model
    }
    return render_template("front/post_detail.html", **context)

在这里插入图片描述

帖子详情页代码的高亮
使用第三方库

https://highlightjs.org/

发表评论
参数校验

class PublicCommentForm(BaseForm):
    content = StringField(validators=[InputRequired(message="请传入内容!")])
    post_id = IntegerField(validators=[InputRequired(message="请传入帖子ID!")])
@bp.post("/comment")
@login_required
def public_comment():
    form = PublicCommentForm(request.form)
    # 校验表单
    if form.validate():
        content = form.content.data
        post_id = form.post_id.data
        try:
            post_model = PostModel.query.get(post_id)
        except Exception as e:
            return restful.params_error(message="帖子不存在!")
        comment = CommentModel(content=content, post_id=post_id, author_id=g.user.id)
        db.session.add(comment)
        db.session.commit()
        return restful.ok()
    else:
        message = form.messages[0]
        return restful.params_error(message=message)

首页获取所有帖子

@bp.route('/')
def index():
    # 获得板块后根据优先级进行排序从大到小
    boards = BoardModel.query.order_by(BoardModel.priority.desc()).all()
    # 获取所有帖子
    posts = PostModel.query.order_by(PostModel.create_time.desc())
    context = {
        "boards": boards,
        "posts": posts,
    }
    return render_template("front/index.html", **context)

在这里插入图片描述

帖子分页
首先我们可以批量生成帖子
commands

# 批量生成帖子
def create_test_posts():
    boards = list(BoardModel.query.all())
    board_count = len(boards)
    for x in range(99):
        title = "我是标题%d"%x
        content = "我是内容%d"%x
        author = UserModel.query.first()
        index = random.randint(0, board_count-1)
        board = boards[index]
        post_model = PostModel(title=title, content=content, author=author,board=board)
        db.session.add(post_model)
    db.session.commit()
    print("测试帖子添加成功")

app.py注册

app.cli.command("create_test_posts")(commands.create_test_posts)
pip install flask-paginate

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

@bp.route('/')
def index():
    sort = request.args.get("st", type=int, default=1)
    # 获得板块后根据优先级进行排序从大到小
    boards = BoardModel.query.order_by(BoardModel.priority.desc()).all()
    post_query = None
    if sort == 1:
        # 按照最近创建的帖子排序
        post_query = PostModel.query.order_by(PostModel.create_time.desc())
    else:
        # 根据评论数量进行排序                 帖子评论外连接                       根据帖子id分组                        计算评论的数量
        post_query = db.session.query(PostModel).outerjoin(CommentModel).group_by(PostModel.id).order_by(func.count(CommentModel.id).desc(), PostModel.create_time.desc())

    page = request.args.get(get_page_parameter(), type=int, default=1)
    # 10-9
    # 210-19
    start = (page - 1) * current_app.config['PER_PAGE_COUNT']
    end = start + current_app.config['PER_PAGE_COUNT']

    # 帖子总数量
    total = post_query.count()
    posts = post_query.slice(start, end)
    pagination = Pagination(bs_version=3, page=page, total=total, prev_label="上一页")

    banners = BannerModel.query.order_by(BannerModel.priority.desc()).all()
    context = {
        "boards": boards,
        "posts": posts,
        "pagination": pagination,
        "st": sort,
        "bd": board_id,
        "banners": banners
    }
    return render_template("front/index.html", **context)

根据板块分页

@bp.route('/')
def index():
    sort = request.args.get("st", type=int, default=1)
    # 板块id
    board_id = request.args.get("bd", type=int, default=None)
    # 获得板块后根据优先级进行排序从大到小
    boards = BoardModel.query.order_by(BoardModel.priority.desc()).all()
    post_query = None
    if sort == 1:
        # 按照最近创建的帖子排序
        post_query = PostModel.query.order_by(PostModel.create_time.desc())
    else:
        # 根据评论数量进行排序                 帖子评论外连接                       根据帖子id分组                        计算评论的数量
        post_query = db.session.query(PostModel).outerjoin(CommentModel).group_by(PostModel.id).order_by(func.count(CommentModel.id).desc(), PostModel.create_time.desc())

    page = request.args.get(get_page_parameter(), type=int, default=1)
    # 10-9
    # 210-19
    start = (page - 1) * current_app.config['PER_PAGE_COUNT']
    end = start + current_app.config['PER_PAGE_COUNT']

    # 如果有板块id 就在之前的基础上再进行过滤
    if board_id:
        # "mapped class CommentModel->comment" has no property "board_id"
        # CommentModel中寻找board_id,然后进行过滤
        # post_query = post_query.filter_by(board_id=board_id)
        post_query = post_query.filter(PostModel.board_id==board_id)
    # 帖子总数量
    total = post_query.count()
    posts = post_query.slice(start, end)
    pagination = Pagination(bs_version=3, page=page, total=total, prev_label="上一页")

    banners = BannerModel.query.order_by(BannerModel.priority.desc()).all()
    context = {
        "boards": boards,
        "posts": posts,
        "pagination": pagination,
        "st": sort,
        "bd": board_id,
        "banners": banners
    }
    return render_template("front/index.html", **context)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

季布,

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值