资讯专栏INFORMATION COLUMN

Flask_Web学习梳理总结(下)

RyanHoo / 3421人阅读

摘要:简单回顾与使用大型组织结构的区别,狗书中从第八章的实例后都采用了蓝本的方式处理路由。故无法显示表单或者文章列表。表示与收藏关系的关联表,使用模型表示。最后放几张总结的脑图和自己基于狗书上的修改轻博客。地址狗书上总结的脑图

简单回顾hello.py与使用大型组织结构的区别,狗书中从第八章的实例后都采用了蓝本的方式处理路由。

import #导入                                                  ---- {分别导入}
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)   #初始化程序
app.config["SECRET_KEY"] = "hard to guess string" #配置       -----{config.py}                                  
migrate = Migrate(app, db)
manager = Manager(app)      #将app连接各个库的初始化            -----{migrate和manager放在manage.py的启动程序上}
bootstrap = Bootstrap(app)         #将app连接各个库的初始化     ------{放在app/__init__.py初始化上}
class NameForm(Form):   #定义表单                              ------{在app/main/forms.py}
class Role(db.Model):
class User(db.Model): #定义模型                                 -------{在app/models.py}
def make_shell_context(): #集成Python shell                    -------{manage.py启动程序上}
def send_async_email(app, msg):
def send_email(to, subject, template, **kwargs): #异步发送邮件  ------{app/email.py上}
@app.errorhandler(404)
@app.errorhandler(500) #处理返回错误模板                         ------{app/main/errors.py}
@app.route("/", methods=["GET", "POST"])                   
@app.route("/user/") #定义视图函数                         ------{app/main/view.py}

书上的内容跟着敲就好了,这里简单分享看狗书过程踩的一些小坑和增加一个收藏功能的实现过程

遇到的一些坑:

数据迁移db upgrade不起作用,更新现有数据库表的粗暴方式是先删除旧表再重新创建

>>>
from manage import db
db.drop_all()
db.create_all()
exit()

第八章代码配置发送邮箱的代码,原代码里的谷歌邮箱已经不能用了(授权码有时会自动更新)

class Config:
    SECRET_KEY = os.environ.get("SECRET_KEY") or "hard to guess string"
    SQLALCHEMY_COMMIT_ON_TEARDOWN = True
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    MAIL_SERVER = "smtp.qq.com"
    MAIL_PORT = 465
    MAIL_USE_TLS = False
    MAIL_USE_SSL = True
    MAIL_USERNAME = "123456789@qq.com"
    MAIL_PASSWORD = "自己邮箱的授权码"
    FLASKY_MAIL_SUBJECT_PREFIX = "[Flasky]"
    FLASKY_MAIL_SENDER = "Admin <123456789@qq.com>"
    FLASKY_ADMIN = "123456789@qq.com"

flask web第11章节遇到博文表单不显示出来

主要是因为在Role没有建立起来的时候(此时在python manage.py shell中,执行Role.query.all()应该得到的是[]),你就先注册了用户,那么此时你的用户角色肯定什么都不是。 故无法显示表单或者文章列表。因此你需要:首先在python manage.py shell中执行Role.insert_roles(), 查询Role.query.all()之后确保得到的结果是[<><>],之后再注册用户; 如果你之前的db中已经包含了你的邮箱或用户名,那么请现在shell中执行

from manage.py import db
db.drop_all() 
db.create_all()

链接:https://www.zhihu.com/questio...

简单实现一个收藏功能:

希望在狗书的基础上给每条博客增加一个收藏按钮,然后在导航栏增加一行“我的收藏”来显示用户收藏的那些博客,下图是我自己改的收藏页面。

首先我们要在博客上增加一个收藏/取消收藏按钮,如果未收藏则显示“收藏”,已经收藏了则显示“未收藏”,改动放在需要被渲染的_post.html独立页面上

div class="post-content">
     
     ...
     
{% if current_user.is_authenticated %} {% if not current_user.is_saving(post) %} Save {% else %} Unsave {% endif %} {% endif %}

判断是否已经收藏过的方法.is_saving(post)需要被写进User模型里,所以我们要考虑一下如何更新Model部分。首先考虑到一个user可以收藏多个post,一个post也可以被不同的user收藏,所以这是一个多对多的关系。多对多关系可以使用定义一对多关系的 db.relationship() 方法进行定义,但是这样定义得到的关联表是一个简单的表,不是模型,会被SQLAlchemy 自动接管。想要储存一些额外的信息,例如user收藏post的时间。为了能处理这些额外的信息,我们必须提升关联表的地位,使关联表变成可访问的模型。表示user与post收藏关系的关联表,使用 Save 模型表示。

class Save(db.Model):
    __tablename__ = "saves"
    saver_id = db.Column(db.Integer, db.ForeignKey("users.id"),
                         primary_key=True)
    saved_id = db.Column(db.Integer, db.ForeignKey("posts.id"),
                         primary_key=True)
    timestamp = db.Column(db.DateTime, default=datetime.utcnow)
    
class User(UserMixin, db.Model):#一个用户可以收藏多篇博客 saveds表示被收藏的博客们
    ...
    saveds = db.relationship("Save",
                             backref=db.backref("saver", lazy="joined"),
                             lazy="dynamic",
                             cascade="all, delete-orphan")
                             
class Post(db.Model): #一篇博客可以被多个用户收藏  savers表示收藏这条博客的用户们
    ...
    savers = db.relationship("Save",
                             backref=db.backref("saved", lazy="joined"),
                             lazy="dynamic",
                             cascade="all, delete-orphan")                                                    
                             

另外.is_saving(post)方法也需要写进User模型里来进行判断当前这个用户是否已经收藏过这篇博客

class User(UserMixin, db.Model): #self表示当前用户在收藏过得博客们里找特定的post
   ...
   def is_saving(self, post):
        return self.saveds.filter_by(
            saved_id=post.id).first() is not None

根据html里面的内容,如果已经收藏过返回true则显示“取消收藏”按钮并返回main.unsave路由;反之则返回main.save路由。这两个路由是来实现收藏博客/取消收藏博客这两个功能并将数据写进数据库里,这样我们下次才能从数据库里查询用户是否收藏过此博客并给出相应的反应。

@main.route("/save/")
@login_required
def save(postid):
    post = Post.query.filter_by(id=postid).first()
    if post is None:
        flash("Invalid post.")
        return redirect(url_for(".index"))
    current_user.savepost(post)   #用户收藏post的方法
    flash("You saved a message")
    return redirect(url_for(".post", id=postid))
    
@main.route("/unsave/")
@login_required
def unsave(postid):
    post = Post.query.filter_by(id=postid).first()
    if post is None:
        flash("Invalid post.")
        return redirect(url_for(".index"))
    current_user.unsavepost(post) #用户取消收藏post的方法
    flash("You unsaved a message")
    return redirect(url_for(".post", id=postid))

用户收藏/取消收藏post的方法的需要写进User模型里

class User(UserMixin, db.Model):
    ...
    def savepost(self, post):
        if not self.is_saving(post):
            f = Save(saver=self, saved=post)  
            db.session.add(f)

    def unsavepost(self, post):
        f = self.saveds.filter_by(saved_id=post.id).first()
        if f:
            db.session.delete(f)

到这里,我们还需要在导航栏里设置一个Pocket导航元素来显示所有被收藏的博客,并将内容写成分页显示出来
base.html加入导航元素Pocket,点击后返回main.pocket路由

视图函数处理Pocket路由,并将分页对象传入pocket.html

@main.route("/pocket", methods=["GET", "POST"])
def pocket():
    page = request.args.get("page", 1, type=int)
    show_saved = True
    query = current_user.saved_posts    #获得所有收藏posts的方法
    pagination = query.order_by(Post.timestamp.desc()).paginate(
        page, per_page=current_app.config["FLASKY_POCKETS_PER_PAGE"],
        error_out=False)
    posts = pagination.items
    return render_template("pocket.html", posts=posts,
                           show_save=show_saved, pagination=pagination)

所以我们还需要在User再加一个.save_posts方法来获取所有收藏的文章展示在pocket.html里

class User(UserMixin, db.Model):
    ...
    @property
    def saved_posts(self):   #联结查询,Post为最后获取内容,从Save查询用户id的所有收藏记录,最后联结过滤
        return db.session.query(Post).select_from(Save). 
            filter_by(saver_id=self.id).join(Post)

最后只需要在pocket.html渲染就好了。
这段时间都在写研究生要投的期刊论文,flask只是抽空自己学学,以后会更新自己专业领域的多目标优化内容和智能算法,很多地方可能没讲清楚,但最要的是能让自己更好的理解。最后放几张总结的脑图和自己基于狗书上的修改轻博客。主要是换了一些板式,增加图片上传,匿名评论和收藏功能。
github地址:https://github.com/kugua233/L...

狗书上总结的脑图

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41565.html

相关文章

  • python10min手写一个服务器内存监控系统

    简易的内存监控系统 本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客 文章源地址,还可以看到具体的代码,喜欢请加个星星 腾讯视频链接 录制中间网出问题了,重启了一下,所以有两部分 视频1 视频2 本文的目的在于,尽可能用简单的代码,让大家了解内存监控的原理主题思路 获取内存信息 存储信息 展现 后续扩展 加主机名,monitor部署在多台机器,不直接插...

    sunsmell 评论0 收藏0
  • python10min手写一个服务器内存监控系统

    简易的内存监控系统 本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客 文章源地址,还可以看到具体的代码,喜欢请加个星星 腾讯视频链接 录制中间网出问题了,重启了一下,所以有两部分 视频1 视频2 本文的目的在于,尽可能用简单的代码,让大家了解内存监控的原理主题思路 获取内存信息 存储信息 展现 后续扩展 加主机名,monitor部署在多台机器,不直接插...

    OBKoro1 评论0 收藏0
  • 第7期 Datawhale 组队学习计划

    马上就要开始啦这次共组织15个组队学习 涵盖了AI领域从理论知识到动手实践的内容 按照下面给出的最完备学习路线分类 难度系数分为低、中、高三档 可以按照需要参加 - 学习路线 - showImg(https://segmentfault.com/img/remote/1460000019082128); showImg(https://segmentfault.com/img/remote/...

    dinfer 评论0 收藏0
  • 那些年,前端学习之路的疑难杂症(三):数组和Date的一些梳理

    摘要:将指定的数字索引值转换成字符串索引值变成,然后将其作为属性名来用。返回一个由删除元素组成的数组。该方法返回的数组元素是调用的数组的一个子集。使用的函数有四个参数初始值积累值数组元素元素索引数组本身。 前言 很多人在学习原生JS的过程中会遇到一些疑惑,比如在学习array时,就很容易搞不清哪些方法会改变原来数组,哪些方法不会改变原来数组?再比如很多人会使用new Date()获取时间,却...

    xeblog 评论0 收藏0
  • Vuex源码学习(一)功能梳理

    摘要:我们通常称之为状态管理模式,用于解决组件间通信的以及多组件共享状态等问题。创建指定命名空间的辅助函数,总结的功能首先分为两大类自己的实例使用为组件中使用便利而提供的辅助函数自己内部对数据状态有两种功能修改数据状态异步同步。 what is Vuex ? 这句话我想每个搜索过Vuex官网文档的人都看到过, 在学习源码前,当然要有一些前提条件了。 了解Vuex的作用,以及他的使用场景。 ...

    livem 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<