• 新闻详情——项目准备——蓝图及模型类设置


    第一步:蓝图模块化

    在info的业务逻辑中,除了会放业务模块还会放其它内容,这里我们需要新建一个文件夹来专门存放这些业务模块

    在info下面,创建一个modules文件夹来存放他们。

     配置蓝图

    在index模块下的init中创建蓝图

    from flask import Blueprint
    
    index_blue = Blueprint("index",__name__)
    
    from . import views

    再在views中导入init,并注册路由

    from . import index_blue
    
    @index_blue.route("/")
    def index():
        #测试redis连接是否成功
        # redis_store.set("name","laoli")
    
        #测试session
        # session["age"] = 28
        return ("hello")

    最后在info>init中导入蓝图并注册路由

    ....
    
    from info.modules.index import index_blue
    
       ....
    def create_app(config_name):
        """创建app的工厂方法
        参数:根据参数选择不同的配置类
        """
    
        ....
      # 注册路由
        app.register_blueprint(index_blue)
        return app

     第二步:表间结构分析

    模型类准备

    因为模型类是属于核心逻辑,我们在info文件夹下创建一个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

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

    1.建立迁移文件

    python manage.py mysql init
    

      

     

     2.生成迁移表

    python manage.py mysql migrate

    当我们运行之后发现并没有生成迁移表

     注意看蓝框,没有改变,是因为app并不知道我们对models做了操作的,在启动文件中导入models

    再运行就可以了

    迁移文件夹中有了一个新的迁移文件。

     

    3.建表

    执行下面命令 

    python manage.py mysql upgrade

     显示下面结果:

     在到mysql去看

    完成了

    4.导入测试数据

    表是空的,自己填不可能的,从sql的脚本来导入测试数据

    进入mysql,找到绑定的数据库,然后再从sql导入数据

    source C:information_info_category.sql
    source C:information_info_news.sql

    这里的两个sql文件要放在没有中文的路径,导入sql文件,要按照上面的顺序来执行

    第三步:主页渲染

    1.解决蓝图导入问题

    蓝图为什么会让导入有问题呢?我们来做个实验就知道了。现在我们有一个需求,就是在访问"/index"路径的时候使用redis来保存一些内容。

    但是当我们导入redis连接对象的时候会发现导不进来,

     我们来到info下的init发现redis_store是灰色的

     这个情况我们之前在db见过,所以我们可以照着写

    info -> __init__.py

     

    这样改完之后会发现不报错了,这就很舒服,但是,当我们运行之后,错误来了:

     

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

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

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

    在manage.py中我们导入了info,之前讲过,导入就会自动执行里面的代码,而info是一个文件夹,所以就会自动执行文件夹中的__init__初始化文件。

     在info中,当执行到下面标注的地方时,直接去到index文件夹中的__init__里面执行初始化了。

    来到index的__init__文件中,我们发现,又导入了views.py这个视图函数文件,

    而在这个views.py视图函数中,它导入了这个redis_store的redis连接对象了。

     

     这个就是原因了,此时这个变量还没生出来呢!

    所以,使用蓝图的时候有一个地方要注意:蓝图在哪里注册,就在它之前导入,避免变量不存在的情况。

    基于这个原因,我们修改一下之前的导入蓝图的地方

    修改之后,测试一下代码,看看redis是否可以使用。

    如果可以正常使用的话,就把之前views.py视图中的测试代码删掉。

    2.主页渲染

    渲染主页相关的两个文件夹static和templates都没放在app同级目录下,默认是放在同级目录下的,我们把它们拖进info目录下

     并将相关的页面放在templates下,我们在templates下新建一个news文件夹来存储新闻页所需要的html文件,把static下的HTML/index.html文件拖进templates的news文件夹中

    最后修改视图函数的相关内容

    3.左侧图标设置

    当我们运行之后会发现我们网页的图标有点low,我们去改一下

     怎么改了,看下面的红框

    (这里我已经设置好了图标的) 因为找不到资源,所以一直报404

    看代码

    from . import index_blue
    from flask import render_template,current_app
    
    @index_blue.route("/")
    def index():
        """
        
        :return: 
        """
        return render_template("news/index.html")
    
    @index_blue.route("/favicon.ico")
    def favicon():
        return current_app.send_static_file("news/favicon.ico")

    说明:current_app是全局app,通常使用它,避免启动文件换名字带来的修改问题

    再次运行,图标就变了

    完成了!

  • 相关阅读:
    查缺补漏中~~
    The number of divisors(约数) about Humble Numbers
    Octorber 21st
    素数回文
    盐水的故事
    居然因为交换错了好几把。。。。,还有坑点是num1可以大于num2
    税收与补贴问题(洛谷1023)
    斐波拉契高精度(洛谷1255)
    高精度模板
    Codeforces#373 Div2
  • 原文地址:https://www.cnblogs.com/Moodsfeelings/p/13765128.html
Copyright © 2020-2023  润新知