文档章节

Python-Flask搭建博客 Day07 后台管理与发布文章

ltoddyc
 ltoddyc
发布于 2017/09/06 19:09
字数 2465
阅读 99
收藏 0
点赞 0
评论 0

源代码: https://github.com/LToddy/blog

技术交流群:630398887(欢迎一起吹牛)

写在前面的话:如果你实在不会写页面,复制粘贴你会吧.

https://getbootstrap.com/docs/3.3/examples/theme/

这个页面是,bootstrap样式表的例样,

http://getbootstrap.com/docs/4.0/examples/

这个页面是,你进去看那个页面合适,你点进去,然后右键查看网页源代码,复制就好了,顺便说一下,别忘了把CSS也复制了.

我们来定义下我们的文章模型,文章内容放到数据库里面,然后通过查询文章标题来,在主页建立文章链接。

<small>app/models.py</small>

class Article(db.Model):
    __tablename__ = 'articles'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64))
    content = db.Column(db.Text)

文章模型很简单,一个id,一个文章标题,一个文章的内容这三个字段。 content = db.Column(db.Text),这里,回顾一下或者百度一下SQLAlchemy的列模型。

因为我们文章内容可不是几个字,而是很多上千上万字说不定,所以就不能再用简单的db.String来处理了。 我们使用db.Text这个,他对长文本做了优化.

当我们有了这个数据库的文章模型之后,为了给数据库添加数据,那么我们还需要相对应的表单:

<small>app/admin/forms.py</small>

class PostForm(FlaskForm):
    title = StringField('文章标题:', validators=[Required()])
    content = TextAreaField('文章内容', validators=[Required()])
    submit = SubmitField('发布')

你看注意看变量的名字,我们最可能的让表单和文章模型中的变量去相同的名字,这样方便。

OK,继续。我们有了表单,要在页面中呈现出来。

<small>app/admin/views.py</small>

from ..models import Article

@admin.route('/', methods=['GET', 'POST'])
def index():
    form = PostForm()
    if not current_user.is_authenticated:
        return redirect(url_for('admin.login'))
    if form.validate_on_submit():
        try:
            article = Article(title=form.title.data, content=form.content.data)
            db.session.add(article)
            form.title.data = ''
            form.content.data = ''
            flash('发布成功')
        except:
            flash('文章标题有重复')
    return render_template('admin/index.html', form=form)

这段代码也没什么难度,先去创建一个表单form,然后判断一下你是否登录了,没登录的话就会重定向到登录界面。 继续往下,让你提交表单的时候,这里用到了一个try - catch语句,其实这里原因是,我最初想把那个数据库文章模型中title字段设置成unique的,title = db.Column(db.String(64),unique=True),后来想想算了,所不定有相同标题的文章呢。然后就是从表单中获取数据,来构件新的文章,然后存到数据库里面。 flash就是用来做一个提示,方便你自己知道你都干了啥事。

OK,把我们的HTML页面也说一下。

{% extends 'admin/base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}

{% block navbar %}
    <nav class="navbar navbar-inverse">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="/">Just for fun</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="/">Home</a></li>
                </ul>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#" data-toggle="dropdown" class="dropdown-toggle">当前用户名为:{{ current_user.username }} <b
                            class="caret"></b></a>
                        <ul class="dropdown-menu">
                            <li><a href="{{ url_for('admin.logout') }}">退出当前账户</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
{% endblock %}

{% block page_content %}
    <div class="page-header">
        {{ wtf.quick_form(form) }}
    </div>
{% endblock %}

唯一做出了更改的地方就是 {% block page_content %}这里,里面加入了一个表单. OK,启动一下我们的项目看看效果。

当然你可能会出现一个SQLAlchemy的异常,如何解决:

$ python3 manage.py shell
>>> from manage import * 
>>> db.drop_all()
>>> db.create_all()
>>> exit()

更新一下我们的数据库结构,毕竟我们更改了数据库模型,添加了文章这个模型。 注意哦,每当我们更改了app/models.py这个文件,我们最好都要重新设置一下数据库.

我们现在已经可以把文章放到数据库了,现在我们要把数据库的文章显示出来。 在这里,我修改了一下templates/base.html页面:

{% extends 'bootstrap/base.html' %}

{% block title %}Just for fun{% endblock %}

{% block navbar %}
    <nav class="navbar navbar-inverse" id="top">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="/">Just for fun</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="/">Home</a></li>
                </ul>
            </div>
        </div>
    </nav>
{% endblock %}

{% block content %}
    {% for message in get_flashed_messages() %}
        <div class="alert alert-info">
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            {{ message }}
        </div>
    {% endfor %}
    <div class="container">
        <div class="col-sm-8">
            {% block page_content %}{% endblock %}
        </div>
        <div class="col-sm-3 col-sm-offset-1">
            {% block slider %}{% endblock %}
        </div>
    </div>
{% endblock %}

只更改了最后,我把<div class="container">,切成了两个块,第一个块来放文章的内容,第二个块来放文章目录。

改完templates/base.html,我们在改一下templates/index.html,这是我们的主页,总显示一句话不好看,所以我们改一改。

{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block page_content %}
    <h1>欢迎来到我的blog</h1>
    <p>技术交流群:630398887</p>
    <hr>
    <div class="row">
        <h2>如下内容凑的字数</h2>
        <hr>
        <h3>登鹳雀楼</h3>
        <p>白日依山尽,黄河入海流。</p>
        <p>欲穷千里目,更上一层楼。</p>
        <hr>
        <h2>论语</h2>
        <p>子谓公冶长:“可妻也,虽在缧绁之中,非其罪也!”以其子妻之。</p>
        <p>子谓南容:“邦有道不废;邦无道免于刑戮。”以其兄之子妻之。</p>
        <p>子谓子贱:“君子哉若人!鲁无君子者,斯焉取斯?”</p>
        <p>子贡问曰:“赐也何如?”子曰:“女器也。”曰:“何器也?”曰:“瑚琏也。”</p>
        <p>或曰:“雍也仁而不佞。”子曰:“焉用佞?御人以口给,屡憎于人。不知其仁,焉用佞?”</p>
        <p>子使漆雕开仕,对曰:“吾斯之未能信。”子说。</p>
        <p>子曰:“道不行,乘桴浮于海,从我者其由与?”子路闻之喜,子曰:“由也好勇过我,无所取材。”</p>
        <p>
            孟武伯问:“子路仁乎?”子曰:“不知也。”又问,子曰:“由也,千乘之国,可使治其赋也,不知其仁也。”“求也何如?”子曰:“求也,千室之邑、百乘之家,可使为之宰也,不知其仁也。”“赤也何如?”子曰:“赤也,束带立于朝,可使与宾客言也,不知其仁也。”</p>
        <p>子谓子贡曰:“女与回也孰愈?”对曰:“赐也何敢望回?回也闻一以知十,赐也闻一以知二。”子曰:“弗如也,吾与女弗如也!”</p>
        <p> 宰予昼寝,子曰:“朽木不可雕也,粪土之墙不可杇也,于予与何诛?”子曰:“始吾于人也,听其言而信其行;今吾于人也,听其言而观其行。于予与改是。”</p>
        <p> 子曰:“吾未见刚者。”或对曰:“申枨。”子曰:“枨也欲,焉得刚。”</p>
        <p> 子贡曰:“我不欲人之加诸我也,吾亦欲无加诸人。”子曰:“赐也,非尔所及也。”</p>
        <p> 子贡曰:“夫子之文章,可得而闻也;夫子之言性与天道,不可得而闻也。”</p>
        <p> 子路有闻,未之能行,唯恐有闻。</p>
        <p> 子贡问曰:“孔文子何以谓之文也?”子曰:“敏而好学,不耻下问,是以谓之文也。”</p>
        <p> 子谓子产:“有君子之道四焉:其行己也恭,其事上也敬,其养民也惠,其使民也义。”</p>
        <p> 子曰:“晏平仲善与人交,久而敬之。”</p>
        <p>
            子张问曰:“令尹子文三仕为令尹,无喜色,三已之无愠色,旧令尹之政必以告新令尹,何如?”子曰:“忠矣。”曰:“仁矣乎?”曰:“未知,焉得仁?”“崔子弑齐君,陈文子有马十乘,弃而违之。至于他邦,则曰:‘犹吾大夫崔子也。’违之。之一邦,则又曰:‘犹吾大夫崔子也。’违之,何如?”子曰:“清矣。”曰:“仁矣乎?”曰:“未知,焉得仁?”</p>
    </div>
{% endblock %}
{% block slider %}
    <ol class="list-unstyled">
        <li><h2>文章列表</h2></li>
        {% for article in articles %}
            <li><a href="article/{{ article.title }}">{{ article.title }}</a></li>
        {% endfor %}
    </ol>
{% endblock %}

当然,大部分内容去百度复制粘贴的,不过这里你要看一下这一段代码。

{% block slider %}
    <ol class="list-unstyled">
        <li><h2>文章列表</h2></li>
        {% for article in articles %}
            <li><a href="article/{{ article.title }}">{{ article.title }}</a></li>
        {% endfor %}
    </ol>
{% endblock %}

我们利用一个for循环,通过视图函数传过来的参数,做了一个文章列表,效果如下:

为了把效果实现出来,我们需要在视图函数中把参数传进来,然后让Jinja2引擎渲染一下。 还记得之前提到Jinja2引擎的时候,它可以想在python里面一样可以解析复杂的数据类型,比如咱这个article。

from ..models import Article


@main.route('/', methods=['GET', 'POST'])
def index():
    articles = Article.query.all()
    return render_template('index.html', articles=articles)

也很简单拉,把所有文章从数据库获取一下,传进去就好了。

能显示文章列表了,我们需要单独把文章显示出来。

<li><a href="admin/article/{{ article.title }}">{{ article.title }}</a></li>

其实阿,这段代码,是我已经把代码都写好了的,因为这个时候你可能还没有把相关的html页面写好。所以说那个 a标签中的href属性可以先不写,然后等会在写就好。

<small>app/templates/article.html</small>

{% extends 'base.html' %}

{% block page_content %}
    <div class="page-header"><h1>{{ title }}</h1></div>
    <div class="well">{{ content }}</div>
{% endblock %}

文章的页面也很简单,一个标题,一个内容。两个变量。

再看一下视图函数:

@main.route('/article/<title>')
def article(title):
    article = Article.query.filter_by(title=title).first()
    return render_template('article.html', title=title, content=article.content)

你看这里,还记得动态路由么,这里用到了动态路由,通过文章的标题来从数据库把这篇文章数据获取出来。 然后把标题和文章内容传参到HTML页面就可以了。

这个时候,你就可以把app/templates/index.html页面中那个文章列表的a标签的href属性补全了。

这里说一下,你看啊,我们的功能在不断的增加,可是基本上都没有大幅度改动我们的原先的代码,而是为新功能写好代码,添加进去。这是一个非常好的表现,增加新功能而又不与原先代码有冲突。

© 著作权归作者所有

共有 人打赏支持
ltoddyc
粉丝 0
博文 8
码字总数 13949
作品 0
淄博
雪峰磁针石博客]flask构建自动化测试平台3-模板

3-模板 理想情况下,前端和后端组件之间的完全隔离。我们可以在很大程度上使用Jinja来实现这一目标。 到本章将扩展我们的应用程序,为所选出版物显示不止一个标题。我们将为每个出版物显示多...

Python测试开发人工智能
07/07
0
0
Linux搭建Python web环境(nginx + flask + uwsgi)

去年的时候,就曾使用Nginx+Flask+uwsgi搭建过python的web环境。但在最近搭建的时候,又去网上找了一遍教程,所以打算写一篇笔记做下记录。 在搭建之前,有必要了解下发送一个请求的整个流程...

liuchungui
05/14
0
0
[雪峰磁针石博客]flask构建自动化测试平台1-hello

简介 第一部分 Flask实例。学习使用Flask开发,构建功能完备的Web应用程序。我们开发了动态的头条新闻应用程序,可显示最新的新闻标题以及最新的货币和天气信息。在项目二中,我们构建了由M...

Python测试开发人工智能
06/09
0
0
【Python搞搞轻量Blog】第一发 Flask入门

大家好,我是仙宇(其实就是咸鱼) 我发现很多小伙伴一直想着有自己的一个博客,而且还想自己写一个。 你们都这么爱折腾,我就给你们搞一个轻量级级别的Blog. 准备 我们要用Python来写一套轻量...

仙宇
03/30
0
0
openshift本地开发环境搭建

有点受不了chinaunix的blog功能了 排版什么不给力 提交文章各种数据丢失 只能说这是一个神奇的网站 自己搭一个博客吧 想来想去 还是用免费的平台比较靠谱 阿里云 新浪什么的忒贵了 我们这种I...

pengfei_xue
2013/02/03
0
0
python-celery使用教程

Celery Celery是Python开发的分布式任务调度模块。分为任务分发,任务队列,worker3个部分。celery的出现,解决了python运行后台任务的需求。 这篇文章介绍的celery版本是3.1.18 celery架构 ...

go-skyblue
2015/07/23
0
0
社区模板的 python 后端实现 - PyFly

项目介绍 PyFly 是 Flask + Layui Fly Template实现的一个社区项目,使用flask-admin实现了简单的后台管理功能,数据库使用Mongodb,前台实现功能:用户注册、登录、邮件激活、发帖、回帖、...

981764793
04/28
0
0
nginx+uwsgi+flask环境搭建

想自己搭建一个Blog,功能不是很复杂,所以选用了python的flask框架,在参照网上的资料搭出Hello World之后将知识汇总一下,以便以后查看。 系统:Ubuntu 14.04 首先安装flask,nginx,pip(方...

L很失败L
2015/08/08
0
2
时隔 8 年,Flask 1.0 终于发布,放弃支持 Py 2.6 和 3.3

(点击上方公众号,可快速关注) 【导读】:在浏览器拼版本号的时代,有些软件的更新,则显得龟速了。比如:2017 年,Python 科学计算库 SciPy 时隔 16 年后才升到 1.0 版。还有,今天本文的...

p5deyt322jacs
05/02
0
0
使用 django-blog-zinnia 搭建个人博客

django-blog-zinnia 虽然小巧,但是具备了个人博客应用的全部基础功能,且具有很高的拓展性,并且开箱即用。以下是官方列出的一些特性: 评论 站点地图(用于搜索引擎优化) 文章归档视图(自...

大数据之路
2012/08/21
0
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring配置xml启动报错 Connot find 'beans'

1.我们先看一下spring的原始配置 <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSc......

江湖鱼大虾
8分钟前
0
0
与女儿谈商业模式 (4):戴尔的成功秘诀

分类:与女儿谈商业模式 | 标签: 戴尔 经济学 陈志武 2007-05-15 10:26阅读(7434)评论(36)   2007年5月《创富志》与“女儿谈商业模式”专栏 (之四)   戴尔的成功秘诀   陈志武   ...

祖冲之
18分钟前
0
0
www.w3.org被qiang导致logback报错:Connect reset

web项目部署到tomcat后,web项目中的logback不能运行,报错信息如下: Reported exception: ch.qos.logback.core.joran.spi.JoranException: I/O error occurred while parsing xml file......

浮躁的码农
32分钟前
0
0
JDeveloper中文乱码解决

全局设置字体; 全局设置环境编码; 项目设置编译器环境编码。

wffger
今天
2
0
MySQL主从介绍 , 准备工作,配置主,配置从, 测试主从同步

MySQL主从介绍 MySQL主从又叫做Replication、AB复制。简单讲就是A和B两台机器做主从后,在A上写数据,另外一台B也会跟着写数据,两者数据实时同步的 MySQL主从是基于binlog的,主上须开启bin...

TaoXu
今天
2
0
线性代数学习总结

亭子happy
今天
1
0
Java8:Lambda表达式增强版Comparator和排序

1、概述 在这篇教程里,我们将要去了解下即将到来的JDK 8(译注,现在JDK 8已经发布了)中的Lambda表达式——特别是怎样使用它来编写Comparator和对集合(Collection)进行排序。 这篇文章是...

孟飞阳
今天
0
0
从架构到组件,深挖istio如何连接、管理和保护微服务2.0?

近几年我一直从事于微服务系统的设计以及实现方面的工作,属于微服务架构一线实践者。之前做过一些单体系统的微服务改造,在微服务拆分、治理等方面都有一定的经验。 本人比较特殊一点的经历...

xiaomin0322
今天
1
0
基于vue的h5文件切片上传(获取文件md5,实现秒传、进度条实现)

template <button @click="file"></button><label ref="upload" style="position: relative;"> <input type="file" @change="selectFile" style="position: abs......

hkaikai
今天
2
0
Spring Boot 2.0 项目实现自同步AD域账号

在通过Spring Boot的自动化装配功能及JDK自带的LDAP模块,可通过如下几个简单步骤实现业务系统自动同步AD域账号功能。 1. Java自带ldap搜索域账号信息核心代码: try { LdapContext ctx...

B超
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部