提交和显示博客文章

文章模型

class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.Text)
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
author_id = db.Column(db.Integer, db.ForeignKey('users.id'))

博客文章表单

app/main/forms.py

class PostForm(FlaskForm):
body = TextAreaField(u'说说',validators=[Required()])
submit = SubmitField(u'发表')

处理博客文章的首页路由

app/main/views.py

@main.route('/',methods=['GET','POST'])
def index():
form = PostForm()
if current_user.can(Permission.WRITE_ARTICLES)and \
form.validate_on_submit():
post = Post(body=form.body.data,author=current_user._get_current_object())
db.session.add(post)
db.session.commit()
return redirect(url_for('.index'))
posts = Post.query.order_by(Post.timestamp.desc()).all()
return render_template('index.html',form=form,posts=posts)

显示博客文章的首页模板

{% extends "base.html" %}
{% import 'bootstrap/wtf.html'as wtf %} {% block title %}Flasky{% endblock %} {% block page_content %}
<div class="page-header">
<h1>欢迎 {% if current_user.is_authenticated %}{{ current_user.username }}{% else %}{% endif %}!</h1>
</div>
<div>
{% if current_user.can(Permission.WRITE_ARTICLES) %}
{{ wtf.quick_form(form) }}
{% endif %}
</div>
<br/>
<br/>
<br/>
<ul class="posts" style="list-style: none">
{% for post in posts %}
<li class="post">
<div class="post-thumbnail">
<a href="{{ url_for('.user',username=post.author.username) }}">
<img class="img-rounded profile-thumbnail" src="{{ post.author.gravatar(size=40) }}" style="float: left">
</a>
</div>
<div class="post-date" style="float: right">{{ moment(post.timestamp).fromNow() }}</div>
<div class="post-author">
<a href="{{ url_for('.user',username=post.author.username) }}" style="padding-left: 20px">
{{ post.author.username }}
</a>
</div>
<div class="post-body" style="padding-left: 60px;padding-bottom: 30px" >{{ post.body }}</div>
</li>
{% endfor %}
</ul>
{% endblock %}

在资料页中显示博客文章

P118

创建虚拟博客文章数据

安装:pip install forgerypy

生成虚拟用户和博客文章

class User(UserMixin,db.Model):
#... @staticmethod
def generate_fake(count=100):
from sqlalchemy.exc import IntegrityError
from random import seed
import forgery_py seed()
for i in range(count):
u = User(email=forgery_py.internet.email_address(),
username=forgery_py.internet.user_name(True),
password=forgery_py.lorem_ipsum.word(),
confirmed=True,
name=forgery_py.name.full_name(),
location=forgery_py.address.city(),
about_me=forgery_py.lorem_ipsum.sentence(),
member_since=forgery_py.date.date(True))
db.session.add(u)
try:
db.session.commit()
except IntegrityError:
db.session.rollback() class Post(db.Model):
@staticmethod
def generate_fake(count=100):
from random import seed, randint
import forgery_py seed()
user_count = User.query.count()
for i in range(count):
u = User.query.offset(randint(0, user_count - 1)).first()
p = Post(body=forgery_py.lorem_ipsum.sentences(randint(1, 5)),
timestamp=forgery_py.date.date(True),
author=u)
db.session.add(p)
db.session.commit()

在puython  shell中生成

  >>>User.genetate_fake(100)

  >>>User.genetate_fake(100)

在页面中渲染数据

@main.route('/',methods=['GET','POST'])
def index():
#... page = request.args.get('page',1,type=int)
pagination = Post.query.order_by(Post.timestamp.desc()).paginate(
page,per_page=current_app.config['FLASKY_POSTS_PER_PAGE'],
error_out=False
)
posts = pagination.items
return render_template('index.html',form=form,posts=posts,pagination=pagination)

添加分页导航

分页导航宏

app/templates/_macros.html

{% macro pagination_widget(pagination, endpoint) %}
<ul class="pagination pagination-lg">
<li{% if not pagination.has_prev %} class="disabled"{% endif %}>
<a href="{% if pagination.has_prev %}{{ url_for(endpoint, page=pagination.prev_num, **kwargs) }}{% else %}#{% endif %}">
&laquo;
</a>
</li>
{% for p in pagination.iter_pages() %}
{% if p %}
{% if p == pagination.page %}
<li class="active">
<a href="{{ url_for(endpoint, page = p, **kwargs) }}">{{ p }}</a>
</li>
{% else %}
<li>
<a href="{{ url_for(endpoint, page = p, **kwargs) }}">{{ p }}</a>
</li>
{% endif %}
{% else %}
<li class="disabled"><a href="#">&hellip;</a></li>
{% endif %}
{% endfor %}
<li{% if not pagination.has_next %} class="disabled"{% endif %}>
<a href="{% if pagination.has_next %}{{ url_for(endpoint, page=pagination.next_num, **kwargs) }}{% else %}#{% endif %}">
&raquo;
</a>
</li>
</ul>
{% endmacro %}

在博客文章列表下面添加分页导航:

app/templates/index.html:

{% extends "base.html" %}
{% import 'bootstrap/wtf.html'as wtf %}
{% import "_macros.html" as macros %} #... {% include '_posts.html' %} #文章 {% if pagination %}
<div class="pagination " style="float: right">
{{ macros.pagination_widget(pagination , '.index') }}
</div>
{% endif %}

使用Markdown和Flask-PageDown支持富文本文章

如果用户想发布长文章,就会觉得在格式上受到了限制。那么就需要使用输入文章的多行文本输入框升级,让其支持Markdown语法,还要添加富文本文章的预览功能

  安装: pip install flask-pagedown markdown bleach

  使用Flask-PageDown

  初始化:

from flask_pagedown import PageDown

pagedown = PageDown()
def create_app(config_name): pagedown.init_app(app) return app

若想把首页的输入框改成Markdown富文本编辑器,PostForm表单中的body字段进行修改。

from flask_pagedown.fields import PageDownField

class PostForm(FlaskForm):
body = PageDownField(u'发表文章',validators=[Required()])
submit = SubmitField(u'确定')

Flask-Pagedown模板声明

{% block scripts %}
{{ super() }}
{{ pagedown.include_pagedown() }}
{% endblock %}

在服务器上处理富文本

提交表单后,POST请求只会发送纯Markdown文本,页面中显示的HTML预览会被丢掉。安全起见,只提交Markdown源文本,在服务器上使用Markdown将其转换成HTML。得到HTML后,再使用Bleach进行清理,确保其中只包含几个允许使用的HTML标签

class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.Text)
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
body_html = db.Column(db.Text) @staticmethod
def on_changed_body(target,value,oldvalue,initiator):
allowed_tags = ['a','abbr','acronym','b','blockquote','code',
'em','i','li','ol','pre','strong','ul',
'h1','h2','h3','p']
target.body_html =bleach.linkify(bleach.clean(markdown(value,output_format='html'),tags=allowed_tags,strip=True))

markdown()函数初步把Markdown文本转换成HTML。然后把得到的结果和允许使用的HTML标签列表传给clean()函数。clean()函数删除所有不在白名单的标签。转换的最后一步由linkify()函数完成,这个函数由Bleach提供,把纯文本中的URL转换成适当的<a>标签。

最后,如果post.body_html字段存在,还要把post.body换成post.body_html:

app/templates/_posts.hrml:在模板中使用文章内容的HTML格式

<div class="post-body" >
{% if post.body_html %}
{{ post.body_html | safe }}
{% else %}
{{ post.body }}
{% endif %}
</div>

博客文章的固定链接

app/main/views.py:文章的固定链接

@main.route('/post/<int:id>')
def post(id):
post = Post.query.get_or_404(id)
return render_template('post.html',posts=[post])

post.html模板接受一个列表作为参数,这个列表就是要渲染的文章。这里必须要传入列表,因为只有这样,index.html和user。html引用的_posts.html模板才能在这个页面中使用。

app/templates/_posts.html:文章的固定链接

        <a href="{{ url_for('.post',id=post.id) }}">
<span class="label label-default">文章</span>
</a>

app/templates/post.html:固定链接模板

{% extends 'base.html' %}
{% block title %}Flask - Post{% endblock %} {% block page_content %}
{% include '_posts.html' %}
{% endblock %}

博客文章编辑器

aapp/main/views.py:编辑博客文章的路由,管理员可以编辑所有的文章

@main.route('/edit/<int:id>',methods=['GET','POST'])
@login_required
def edit(id):
post = Post.query.get_or_404(id)
if current_user != post.author and \
not current_user.can(Permission.ADMINISTER):
abort(403)
form = PostForm()
if form.validate_on_submit():
post.body = form.body.data
db.session.add(post)
db.session.commit()
flash('The post has been updated.')
return redirect(url_for('.post',id=post.id))
form.body.data = post.body
return render_template('edit_post.html',form=form)

app/templates/_posts.html:编辑博客文章的链接

        {% if current_user == post.author %}
<a href="{{ url_for('.edit',id=post.id) }}">
<span class="label label-primary">编辑</span>
</a>
{% elif current_user.is_administrator() %}
<a href="{{ url_for('.edit',id=post.id) }}">
<span class="label label-danger">编辑</span>
</a>
{% endif %}

app/templates/edit_post.html:编辑博客文章的模板.

{% extends 'base.html' %}
{% import 'bootstrap/wtf.html'as wtf %} {% block title %}Flask-edit{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Edit Post</h1>
</div>
<div>
{{ wtf.quick_form(form) }}
</div>
{% endblock %} {% block scripts %}
{{ super() }}
{{ pagedown.include_pagedown() }}
{% endblock %}

flask-博客文章的更多相关文章

  1. Flask 学习 十 博客文章

    提交和显示博客文章 app/models.py 文章模型 class Post(db.Model): __tablename__ = 'posts' id = db.Column(db.Integer ...

  2. 用 Flask 来写个轻博客 (22) — 实现博客文章的添加和编辑页面

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 新建表单 新建视图函数 新建模板 在博客文章页面添加 New 和 Ed ...

  3. Flask博客开发——Tinymce编辑器

    之前Flask博客的文本编辑器比较简陋,这里为博客添加个优雅易用的Tinymce文本编辑器. 1.项目中添加Tinymce 下载好Tinymce包以及语言包,并添加到项目中.添加到项目的方法,参考了这 ...

  4. Flask博客开发——自定义头像

    Flask Web开发一书中,使用了与个人邮箱绑定的Gravatar图形作为用户头像.Gravatar提供的头像比较简陋,而且可能由于网络问题无法生成头像.多数社交网站和博客提供用户自定义头像功能,因 ...

  5. SQL Sever 博客文章目录(2016-07-06更新)

    SQL Server方面的博客文章也陆陆续续的写了不少了,顺便也将这些知识点整理.归纳一下下.方便自己和他人查看. MS SQL 数据类型 三大数据库对比研究系列--数据类型 MS SQL 表和视图 ...

  6. 使用 Microsoft Word 发布博客文章

    以 Microsoft Word 2010 为例: 依次选择:文件 -> 保存并发送 -> 发布为博客文章 配置说明:新建账户 的 博客文章 URL  一栏填写 http://rpc.cn ...

  7. 年度十佳 DevOps 博客文章(后篇)

    如果说 15 年你还没有将 DevOps 真正应用起来,16 年再不实践也未免太落伍了.在上篇文章中我们了解到 15 年十佳 DevOps 博客文章的第 6-10 名,有没有哪一篇抓住了您的眼球,让您 ...

  8. 年度十佳 DevOps 博客文章(前篇)

    如果说 15 年你还没有将 DevOps 真正应用起来,16 年再不实践也未免太落伍了.国内 ITOM 领军企业 OneAPM 工程师为您翻译整理了,2015 年十佳 DevOps 文章,究竟是不是深 ...

  9. Word 2010发布博客文章

    只测试了cnblog 1.新建文件选择word 2010自带的博客文章模板 2.在管理账户中新建一个博客账户,也就是你自己在博客园的账户,博客选其他 3.然后选择下一步,博客的URL在自己的博客设置里 ...

  10. VM 映像 PowerShell 教学系列博客文章

     编辑人员注释:本文章是与Microsoft Azure工程的项目经理Kay Singh共同撰写的 正如我在第一篇博客文章中所承诺的,我又回来了,为大家分步介绍如何在PowerShell中使用VM ...

随机推荐

  1. nginx的基本操作

    启动 nginx -c /etc/nginx/nginx.conf停止nginx -s stop nginx -s quit pkill -9 nginx重载nginx -s reload文件检测ng ...

  2. noip搜索模拟题 骰子

    骰子 dice.cpp/c/pas 1s/128M [题目描述] 桌面上有两个特别的骰子.骰子的每一个面,都写了一个不同的数字.设第一个骰子上下左右前后分别为a1, a2, a3, a4, a5, a ...

  3. Linux环境 Java内存快速查看

    最近生产环境遇到内存老是占用很大的情况,16G的内存Free的内存只剩100多M,仿佛一颗定时炸弹一般,说不定就服务Down了.于是开始网上不断的找查看内存使用的方法.现学现卖,以下通过一个例子来演示 ...

  4. ubuntu 14.04 安装minidwep-gtk

    一,安装相关的依赖 sudo apt-get install build-essential libssl-dev iw libpcap-dev sqlite3 libsqlite3-dev libp ...

  5. Windows基础环境_安装配置教程(Windows7 64、JDK1.8、Android SDK23.0、TortoiseSVN 1.9.5)

    Windows基础环境_安装配置教程(Windows7 64.JDK1.8.Android SDK23.0.TortoiseSVN 1.9.5) 安装包版本 1)     JDK版本包 地址: htt ...

  6. .NET easyUI tree树状结构

    简单的制作后台制作写一个json(string类型)格式 public partial class goodstype_type : System.Web.UI.Page { public strin ...

  7. 洛谷 P3387 【模板】缩点

    题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只 ...

  8. 会写网页 就会写手机APP #2-- 范例修正 , Hybrid Mobile Apps for ASP.NET Developers (Apache Cordova)

    原文出处:会写网页 就会写手机APP #2-- 范例修正 , Hybrid Mobile Apps for ASP.NET Developers (Apache Cordova) 这是我的文章备份  ...

  9. 使用工具Source Monitor测量您Java代码的环复杂度

    代码的环复杂度(Cyclomatic complexity,有时也翻译成圈复杂度)是一种代码复杂度的衡量标准,在1976年由Thomas J. McCabe, Sr. 提出. 来看看计算公式. 代码环 ...

  10. IT界程序员几大恶习能立即让你变穷,你有吗?

    IT软件开发,确实是各行业中薪水排名靠前的职业,月薪在八千以上的Java程序员多不胜数,但是不知有没有以下几种恶习?如果粘上一种,哪怕你薪水几万,估计最后也是囊中羞涩:综上所述列举以下几点,亲们自己对 ...