flask项目——模型类设置以及数据迁移和主页渲染

1. 表间结构分析及模型类准备

表间结构示意图:

 模型类准备:

在info文件夹中存储着我们的所有的业务逻辑,所以,我们可以在info中新建一个名为models.py的python文件,用于存储模型类定义的相关代码。

在models.py中放入下面的代码

from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash

from info import constants
from . import db


class BaseModel(object):
    """模型基类,为每个模型补充创建时间与更新时间"""
    create_time = db.Column(db.DateTime, default=datetime.now)  # 记录的创建时间
    update_time = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now)  # 记录的更新时间


# 用户收藏表,建立用户与其收藏新闻多对多的关系
tb_user_collection = db.Table(
    "info_user_collection",
    db.Column("user_id", db.Integer, db.ForeignKey("info_user.id"), primary_key=True),  # 新闻编号
    db.Column("news_id", db.Integer, db.ForeignKey("info_news.id"), primary_key=True),  # 分类编号
    db.Column("create_time", db.DateTime, default=datetime.now)  # 收藏创建时间
)

tb_user_follows = db.Table(
    "info_user_fans",
    db.Column('follower_id', db.Integer, db.ForeignKey('info_user.id'), primary_key=True),  # 粉丝id
    db.Column('followed_id', db.Integer, db.ForeignKey('info_user.id'), primary_key=True)  # 被关注人的id
)


class User(BaseModel, db.Model):
    """用户"""
    __tablename__ = "info_user"

    id = db.Column(db.Integer, primary_key=True)  # 用户编号
    nick_name = db.Column(db.String(32), unique=True, nullable=False)  # 用户昵称
    password_hash = db.Column(db.String(128), nullable=False)  # 加密的密码
    mobile = db.Column(db.String(11), unique=True, nullable=False)  # 手机号
    avatar_url = db.Column(db.String(256))  # 用户头像路径
    last_login = db.Column(db.DateTime, default=datetime.now)  # 最后一次登录时间
    is_admin = db.Column(db.Boolean, default=False)
    signature = db.Column(db.String(512))  # 用户签名
    gender = db.Column(        # 性别
        db.Enum(
            "MAN",  #
            "WOMAN"  #
        ),
        default="MAN")

    # 当前用户收藏的所有新闻
    collection_news = db.relationship("News", secondary=tb_user_collection, lazy="dynamic")  # 用户收藏的新闻
    # 用户所有的粉丝,添加了反向引用followed,代表用户都关注了哪些人
    followers = db.relationship('User',
                                secondary=tb_user_follows,
                                primaryjoin=id == tb_user_follows.c.followed_id,
                                secondaryjoin=id == tb_user_follows.c.follower_id,
                                backref=db.backref('followed', lazy='dynamic'),
                                lazy='dynamic')

    # 当前用户所发布的新闻
    news_list = db.relationship('News', backref='user', lazy='dynamic')

    def to_dict(self):
        resp_dict = {
            "id": self.id,
            "nick_name": self.nick_name,
            "avatar_url": constants.QINIU_DOMIN_PREFIX + self.avatar_url if self.avatar_url else "",
            "mobile": self.mobile,
            "gender": self.gender if self.gender else "MAN",
            "signature": self.signature if self.signature else "",
            "followers_count": self.followers.count(),
            "news_count": self.news_list.count()
        }
        return resp_dict

    def to_admin_dict(self):
        resp_dict = {
            "id": self.id,
            "nick_name": self.nick_name,
            "mobile": self.mobile,
            "register": self.create_time.strftime("%Y-%m-%d %H:%M:%S"),
            "last_login": self.last_login.strftime("%Y-%m-%d %H:%M:%S"),
        }
        return resp_dict


class News(BaseModel, db.Model):
    """新闻"""
    __tablename__ = "info_news"

    id = db.Column(db.Integer, primary_key=True)  # 新闻编号
    title = db.Column(db.String(256), nullable=False)  # 新闻标题
    source = db.Column(db.String(64), nullable=False)  # 新闻来源
    digest = db.Column(db.String(512), nullable=False)  # 新闻摘要
    content = db.Column(db.Text, nullable=False)  # 新闻内容
    clicks = db.Column(db.Integer, default=0)  # 浏览量
    index_image_url = db.Column(db.String(256))  # 新闻列表图片路径
    category_id = db.Column(db.Integer, db.ForeignKey("info_category.id"))
    user_id = db.Column(db.Integer, db.ForeignKey("info_user.id"))  # 当前新闻的作者id
    status = db.Column(db.Integer, default=0)  # 当前新闻状态 如果为0代表审核通过,1代表审核中,-1代表审核不通过
    reason = db.Column(db.String(256))  # 未通过原因,status = -1 的时候使用
    # 当前新闻的所有评论
    comments = db.relationship("Comment", lazy="dynamic")

    def to_review_dict(self):
        resp_dict = {
            "id": self.id,
            "title": self.title,
            "create_time": self.create_time.strftime("%Y-%m-%d %H:%M:%S"),
            "status": self.status,
            "reason": self.reason if self.reason else ""
        }
        return resp_dict

    def to_basic_dict(self):
        resp_dict = {
            "id": self.id,
            "title": self.title,
            "source": self.source,
            "digest": self.digest,
            "create_time": self.create_time.strftime("%Y-%m-%d %H:%M:%S"),
            "index_image_url": self.index_image_url,
            "clicks": self.clicks,
        }
        return resp_dict

    def to_dict(self):
        resp_dict = {
            "id": self.id,
            "title": self.title,
            "source": self.source,
            "digest": self.digest,
            "create_time": self.create_time.strftime("%Y-%m-%d %H:%M:%S"),
            "content": self.content,
            "comments_count": self.comments.count(),
            "clicks": self.clicks,
            "category": self.category.to_dict(),
            "index_image_url": self.index_image_url,
            "author": self.user.to_dict() if self.user else None
        }
        return resp_dict


class Comment(BaseModel, db.Model):
    """评论"""
    __tablename__ = "info_comment"

    id = db.Column(db.Integer, primary_key=True)  # 评论编号
    user_id = db.Column(db.Integer, db.ForeignKey("info_user.id"), nullable=False)  # 用户id
    news_id = db.Column(db.Integer, db.ForeignKey("info_news.id"), nullable=False)  # 新闻id
    content = db.Column(db.Text, nullable=False)  # 评论内容
    parent_id = db.Column(db.Integer, db.ForeignKey("info_comment.id"))  # 父评论id
    parent = db.relationship("Comment", remote_side=[id])  # 自关联
    like_count = db.Column(db.Integer, default=0)  # 点赞条数

    def to_dict(self):
        resp_dict = {
            "id": self.id,
            "create_time": self.create_time.strftime("%Y-%m-%d %H:%M:%S"),
            "content": self.content,
            "parent": self.parent.to_dict() if self.parent else None,
            "user": User.query.get(self.user_id).to_dict(),
            "news_id": self.news_id,
            "like_count": self.like_count
        }
        return resp_dict


class CommentLike(BaseModel, db.Model):
    """评论点赞"""
    __tablename__ = "info_comment_like"
    comment_id = db.Column("comment_id", db.Integer, db.ForeignKey("info_comment.id"), primary_key=True)  # 评论编号
    user_id = db.Column("user_id", db.Integer, db.ForeignKey("info_user.id"), primary_key=True)  # 用户编号


class Category(BaseModel, db.Model):
    """新闻分类"""
    __tablename__ = "info_category"

    id = db.Column(db.Integer, primary_key=True)  # 分类编号
    name = db.Column(db.String(64), nullable=False)  # 分类名
    news_list = db.relationship('News', backref='category', lazy='dynamic')

    def to_dict(self):
        resp_dict = {
            "id": self.id,
            "name": self.name
        }
        return resp_dict
View Code

说明:

  1. 导入时间是因为我们在模型类中用到了时间
  2. 文件中导入了两个库 generate_password_hash, check_password_hash,第一个是用来加密密码的,第二个是用来校验密码是否正确的
  3. 导入的时候还导入了constants的文件,这个文件目前我们并没创建,里面存放着一些常量信息。

 在info文件夹中新建一个constants.py文件用来存储一些常量信息:

# 图片验证码Redis有效期, 单位:秒
IMAGE_CODE_REDIS_EXPIRES = 300

# 短信验证码Redis有效期,单位:秒
SMS_CODE_REDIS_EXPIRES = 300

# 七牛空间域名
QINIU_DOMIN_PREFIX = "http://oyucyko3w.bkt.clouddn.com/"

# 首页展示最多的新闻数量
HOME_PAGE_MAX_NEWS = 10

# 用户的关注每一页最多数量
USER_FOLLOWED_MAX_COUNT = 4

# 用户收藏最多新闻数量
USER_COLLECTION_MAX_NEWS = 10

# 其他用户每一页最多新闻数量
OTHER_NEWS_PAGE_MAX_COUNT = 10

# 点击排行展示的最多新闻数据
CLICK_RANK_MAX_NEWS = 10

# 管理员页面用户每页多最数据条数
ADMIN_USER_PAGE_MAX_COUNT = 10

# 管理员页面新闻每页多最数据条数
ADMIN_NEWS_PAGE_MAX_COUNT = 10
View Code

2. 建立迁移所用文件夹

接下来我们使用命令来完成建表等操作:

python manage.py mysql init

 

 

3.生成迁移表

在建表之前一定要先在我们的manage.py中加入导入的相关命令:

from info import models

然后再执行相关操作

python manage.py mysql migrate

 注:

 这里报错,有两种情况,第一种数据库密码不对,第二种数据库链接地址要改成双引号,具体问题我也不知道,灵异事件,时成时不成的,报错了可以试试

这个样子基本上就成了

 

 4. 建表

执行下面命令:

python manage.py mysql upgrade

看到这个基本就成了

 然后到MySQL中看一下,成了,我们就可以执行之后的操作了

 

5.在MySQL中导入测试数据

首先我们找到测试数据位置,并且进入到MySQL中去

经行以下操作

source D:StudyCodeinformation_info_category.sql
source D:StudyCodeinformation_info_news.sql

说明:这里两个sql文件要放到没有中文路径的地方;在导入执行sql脚本的时候,要按上面的执行顺序来执行。

 

 看到这两个,基本就成了,然后查看一下表,有没有乱码,首先我们查看一下所有的表

 再然后我们随便查看一个表中的数据

 

 看到这里,没有乱码,基本就成了

6.主页渲染

我们在看info这个文件的_init_.py这个文件时,可以看到,redis_store还报着灰呢,下面我们来解决一下

 我们之前解决过类似这样的问题(db)

所以我们照葫芦画瓢

 然后我们运行一下

 报错了

 这个异常时ImportError,通常这个异常产生的原因有两个:

  1. 导入错误
  2. 导入某个变量的时候,这个变量还不存在

这里导入错误产生的原因就是第二种,此时变量还不存在。

因为在db之前就在要redis_store,但是此时还没有这个参数,但是db我们的位置没法改,所以我们改一下蓝图的导入位置,什么时候要蓝图,什么时候导入,所以我们把蓝图导入放到最后。(稍微有点儿绕,绕晕了)

 然后我们在运行一下,基本就成了。

7.主页渲染

渲染主页肯定会用到html文件,而这些文件默认会放到和app同级目录下的templates文件夹中,而目前,我们的app在info的__init__文件中。

所以,我们将默认的templates文件夹放到info目录下,同时,将默认的生成的static文件夹也放到里面。

操作完成之后,将提供的相关文件放到static文件夹当中,并在templates文件夹中新建一个news文件来存储新闻页所需要的html文件。

操作之后,把我们需要渲染的模板扔到news文件夹下:

 然后我们修改视图函数中的相关内容,完成页面的渲染就可以了。

from . import index_blue
from flask import render_template


@index_blue.route("/index")
def index():
    """
        主页功能
    :return: 
    """
    return render_template("news/index.html")

8.左侧小log

别的人这个位置都有一个自己的对应的小脚标

看着好看,所有咱们也不能拉下,咱们也得有自己的小脚标

 首先我们导入一个 current_app (是全局的app,通常我们会使用它,避免启动文件换名字带来的修改问题),然后我们给他注册个蓝图

@index_blue.route("/favicon.ico")
def favicon():
    """
    title左侧图标
    :return:
    """

    return current_app.send_static_file("news/favicon.ico")

运行代码,然后他就出来,然后就成了

原文地址:https://www.cnblogs.com/ls011218/p/13768863.html