flask实战-个人博客-程序骨架、创建数据库模型、临接列表关系 --
编写程序骨架
personalBlog的功能主要分为三部分:博客前台、用户认证、博客后台,其中包含的功能点如下图所示:

数据库
personalBlog一共需要使用四张表,分别存储管理员(Admin)、分类(Category),文章(Post)和评论(Comment)。
1、创建数据库模型
1)管理员
如果是编写一个固定的个人博客,那么事情就要简单得多,博客的大部分固定信息(比如博客标题,页脚信息等)都可以直接写死在模板中,或是使用自定义的配置存储在配置文件中。但是我们希望编写的是一个通用的博客平台,这就意味着我们要把这些信息的设置交给最终的用户。
为了让博客管理员可以更方便地修改博客信息,我们要提供博客信息(比如博客标题和副标题)修改功能。这些信息不能仅仅定义在配置文件中,而要存储到数据库中。这样用户可以方便地在程序界面修改设置,而不用手动编辑配置文件。
我们将创建一个admin类表示管理员模型,管理员的资料和博客的资料都通过它来保存。
personalBlog/models.py:管理员模型
from personalBlog.extensions import db class Admin(db.Model):
id = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(20))
password_hash = db.Column(db.string(128))
blog_title = db.Column(db.string(60))
blog_sub_title = db.Column(db.String(100))
name = db.Column(db.String(30))
about = db.Column(db.Text)
除了主键字段(id),管理员模型包含存储用户信息和博客资料的字段:用户姓名(name)、密码散列值(password_hash)、博客标题(blog_title)、博客股标题(blog_sub_title)、关于信息(about)。
在这些字段中,我们并没有添加一个password字段来存储密码,取而代之的是一个password_hash字段,后面我们会详细了解具体的原因。
当然,在真实的博客平台中,用户还会拥有更多的可定义设置保存在数据库中,比如用来发送提醒邮件的邮箱服务器、每页显示的文章数量等。这里我们的目标是一个尽量简单的博客平台,所以大部分设置都保存在配置文件中。
2)分类
用于存储文章分类的数据库模型如下所示:
class Category(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(30), unique = True)
分类的名称不允许重复,因此name值将unique参数设为True。
3)文章
存储文章Post模型有标题(title)字段、正文(body)字段以及时间戳(timestamp)字段组成,如下所示:
personalBlog/models.py:文章模型
from datetime import datetime class Post(db.Model):
id = db.Column(db.Integer, primary_key = True)
title = db.Column(db.String(60))
body = db.Column(db.Text)
timestamp = db.Column(db.DateTime, default = datetime.utcnow)
在分类和文章之间需要建立一对多关系。我们为Post模型添加了一个category_id外键字段,作为指向分类模型的外键,存储分类记录的主键值,同时在Post类中创建标量关系属性category,在category类中创建集合关系属性posts,如下所示:
class Category(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(30), unique = True)
posts = db.relationship('Post', back_populates = 'category') class Post(db.Model):
id = db.Column(db.Integer, primary_key = True)
title = db.Column(db.String(60))
body = db.Column(db.Text)
timestamp = db.Column(db.DateTime, default = datetime.utcnow)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
category = db.relationship('Category', back_populates = 'posts')
4)评论
用来存储评论的模型类Comment如下所示:
personalBlog/models.py: 评论模型
class Comment(db.Model):
id = db.Column(db.Integer, primary_key = True)
author = db.Column(db.String(30))
email = db.Column(db.String(254))
site = db.Column(db.String(255))
body = db.Column(db.Text)
from_admin = db.Column(db.Boolean, default = False)
reviewed = db.Column(db.Boolean, default = False)
timestamp = db.Column(db.DateTime, default = datetime.utcnow, index = True)
除了作者(author)、电子邮件(email)、站点(site)、正文(body)这几个常规字段,Comment模型还包含这两个特殊字段:from_admin字段存储布尔值,用来判断评论是否是管理员的评论,默认为False;reviewed字段也存储布尔值,用来判断评论是否通过审核。
添加reviewd字段的主要目的是为了防止垃圾评论和不当评论,当用户发表评论后,评论不会立刻显示在博客中,只有当管理员在博客后台查看并批准后才会显示。
每篇文章都可以包含多个评论,文章和评论之间是一对多双向关系:
class Post(db.Model):
id = db.Column(db.Integer, primary_key = True)
title = db.Column(db.String(60))
body = db.Column(db.Text)
timestamp = db.Column(db.DateTime, default = datetime.utcnow)
category_id = db.Column(db.Integer, db.foreignKey('category.id'))
category = db.relationship('Category', back_populates = 'posts')
# cascade:级联操作
comments = db.relationship('Comment', back_populates = 'post', cascade = 'all') class Comment(db.Model):
id = db.Column(db.Integer, primary_key = True)
author = db.Column(db.String(30))
email = db.Column(db.String(254))
site = db.Column(db.String(255))
body = db.Column(db.Text)
from_admin = db.Column(db.Boolean, default = False)
reviewed = db.Column(db.Boolean, default = False)
timestamp = db.Column(db.DateTime, default = datetime.utcnow, index = True)
post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
post = db.relationship('Post', back_populates = 'comments')
Comment模型中创建的外键字段post_id存储Post记录的主键值。我们在这里设置了级联删除,也就是说,当某个记录被删除时,该文章所属的所有评论也会一并被删除,所以在删除文章时不用手动删除对应的评论。
2、临接列表关系
与messageBoard不同,博客程序中的评论要支持存储回复。我们想要为评论添加回复,并在获取某个评论时通过关系属性获得相对应的回复,这样就可以在模板中显示出评论之间的对应关系。那么回复如何存储在数据库中呢?
你当然可以再为回复创建一个Reply模型,然后使用一对多关系将评论和回复关联起来。但是我们将介绍一个更简单的解决办法,因为回复本身也是评论,如果可以在评论模型内建立层级关系,那么就可以在一个模型中表示评论和回复。
这种在同一个模型内的一对多关系在SQLAlchemy中被称为临接列表关系(Adjacency List Relationship)。具体来说,我们需要在Comment模型中添加一个外键指向它自身。这样我们就得到一种层级关系:每个评论对象都可以包含多个评论,即回复。
下面是更新后的comment模型:
class Comment(db.Model):
id = db.Column(db.Integer, primary_key = True)
author = db.Column(db.String(30))
email = db.Column(db.String(254))
site = db.Column(db.String(255))
body = db.Column(db.Text)
from_admin = db.Column(db.Boolean, default = False)
reviewed = db.Column(db.Boolean, default = False)
timestamp = db.Column(db.DateTime, default = datetime.utcnow, index = True)
post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
post = db.relationship('Post', back_populates = 'comments') replied_id = db.Column(db.Integer, db.ForeignKey('comment.id'))
replied = db.relationship('Comment', back_populates = 'replies', remote_side = [id])
replies = db.relationship('Comment', back_populates = 'replied', cascade = 'all')
在Comment模型中,我们添加了一个replied_id字段,通过db.ForeignKey()设置一个外键指向自身的id字段:
replied_id = db.Column(db.Integer, db.ForeignKey('comment.id'))
关系两侧的关系属性都在Comment模型中定义,需要特别说明的是表示被回复评论(父对象)的标量关系属性replied的定义。
这个关系和我们之前熟悉的一对多关系基本相同。一对多关系中,我们需要在“多”这一侧定义外键,这样SQLAlchemy就会知道哪边是“多”的一侧。这时关系对“多”这一侧来说就是多对一关系。但是在临接列表关系中,关系的两侧都在同一个模型中,这时SQLAlchemy就无法分辨关系的两侧。在这个关系函数中,通过remote_side参数设为id字段,我们就把id字段定义为关系的远程侧(Remote Side),而replied_id就响应地变为本地侧(Local Side),这样反向关系就被定义为多对一,即多个回复对应一个父评论。
集合关系属性replies中的cascade参数设为all,因为我们期望的效果是,当父评论被删除时,所有的自评论也随之删除。
flask实战-个人博客-程序骨架、创建数据库模型、临接列表关系 --的更多相关文章
- flask实战-个人博客-使用工厂函数创建程序实例 --
使用工厂函数创建程序实例 使用蓝本还有一个重要的好处,那就是允许使用工厂函数来创建程序实例.在OOP(Object-Oriented Programming,面向对象编程)中,工厂(factory)是 ...
- flask实战-个人博客-使用蓝本模块化程序
使用蓝本模块化程序 实例化flask提供的blueprint类就创建一个蓝本实例.像程序实例一样,我们可以为蓝本实例注册路由.错误处理函数.上下文处理函数,请求处理函数,甚至是单独的静态文件文件夹和模 ...
- flask实战-个人博客-虚拟环境、项目结构
个人博客 博客是典型的CMS(Content Management system,内容管理系统),通常由两部分组成:一部分是博客前台,用来展示开放给所有用户的博客内容:另一部分是博客后台,这部分内容仅 ...
- flask实战-个人博客-编写博客前台
编写博客前台 博客前台需要开放给所有用户,这里包括显示文章列表.博客信息.文章内容和评论等功能功能. 分页显示文章列表 为了在主页显示文章列表,我们要先在渲染主页模板的index视图的数据库中获取所有 ...
- flask实战-个人博客-电子邮件支持
电子邮件支持 因为博客要支持评论,所以我们需要在文章有了新评论后发邮件通知管理员.而且,当管理员回复了读者的评论后,也需要发送邮件提醒读者. 为了方便读者使用示例程序,personalBlog中仍然使 ...
- flask实战-个人博客-模板 --
模板 personalBlog采用典型的博客布局,左侧三分之二为主体,显示文章列表.正文:右侧三分之一为边栏,显示分为类列表.社交链接等.现在的工作是将HTML文件加工为模板,并创建对应的表单类,在模 ...
- flask实战-个人博客-数据库-生成虚拟数据 --
3.生成虚拟数据 为了方便编写程序前台和后台功能,我们在创建数据库模型后就编写生成虚拟数据的函数. 1)管理员 用于生成虚拟管理员信息的fake_admin()函数如下所示: personalBlog ...
- flask实战-个人博客-表单
表单 下面我们来编写所有表单类,personalBlog中主要包含下面这些表单: 登录表单: 文章表单: 评论表单: 博客设置表单: 这里仅介绍登录表单.文章表单.分类表单和评论表单,其他的表单在实现 ...
- flask实战-个人博客-使用类组织配置
使用类组织配置 在实际需求中,我们往往需要不同的配置组合.例如,开发用的配置,测试用的配置,生产环境用的配置.为了能方便地在这些配置中切换,你可以把配置文件升级为包,然后为这些使用场景分别创建不同的配 ...
随机推荐
- Xcode一个project多个target
project添加target https://blog.csdn.net/vbirdbest/article/details/53466009 https://www.cnblogs.com/Bob ...
- SpringMvc通过controller上传文件代码示例
上传文件这个功能用的比较多,不难,但是每次写都很别扭.记录在此,以备以后copy用. package com.**.**.**.web.api; import io.swagger.annotatio ...
- 【视频开发】【计算机视觉】相机标定(Camera calibration)《二》
简介 摄像机标定(Camera calibration)简单来说是从世界坐标系换到图像坐标系的过程,也就是求最终的投影矩阵 P 的过程,下面相关的部分主要参考UIUC的计算机视觉的课件(网址Sprin ...
- 【神经网络与深度学习】neural-style、chainer-fast-neuralstyle图像风格转换使用
neural-style 官方地址:这个是使用torch7实现的;torch7安装比较麻烦.我这里使用的是大神使用TensorFlow实现的https://github.com/anishathaly ...
- Linux 就该这么学 CH06 存储结构与磁盘划分
1.一切从"/"开始 linux系统中一切都是文件,而且一切文件的路径都是从根目录(/)开始的.系统中的根目录和文件名称都是严格区分大小写的,并且文件名中不能包含/符号. 绝对路径 ...
- (一)将mockjs集成到VUE中后,怎样根据接口入参返回mock结果
1)安装mockjs,这一步跳过 2)在项目中建立mock模块,笔者的目录结构如下 mock模块与接口模块一一对应,有一个接口,就有一个mock 3)编写登陆模块mock接口,代码如下: import ...
- AGC039
Contest Page A 对于一个长度为\(L\)的相同字符段,显然要花费\(\frac{L}{2}\)次操作才能使得相邻不相同.于是只需要分类讨论一下首尾字符是否相同,算出每种字符.每种长度的连 ...
- Linux学习笔记之vim操作指令大全
0x00 关于Vim Vim是款强大的文本编辑器,但是众多指令需要学习,这次记录了指令大全方便以后翻阅. Vim的几种模式 正常模式:可以使用快捷键命令,或按:输入命令行. 插入模式:可以输入文本,在 ...
- [其它]iOS 13 正式版发布 iPhone 6s或更新型号均可升级
苹果今天(2019.09.20)发布了 iOS 13 正式版,可以升级的设备包括 iPhone 6s 或更新型号.第七代 iPod Touch. iOS 13 推出深色模式,为 iPhone 带来截然 ...
- 无法打开内核设备:\\Global\\vmx86
关于如题目的问题,网上有好几个解决办法,这里只介绍最方便的一个办法,利用脚本来解决 @Echo Off title Hankcs's program color 8F CD %~d0 CD %~dp0 ...