美文网首页程序员编程地带
Flask学习(十一) - 阶段总结&案例

Flask学习(十一) - 阶段总结&案例

作者: MA木易YA | 来源:发表于2018-11-26 20:41 被阅读8次

    阶段总结

          这一阵子对flask的学习主要是参考文档和网易云课堂的视频教程,简单了解的项目结构搭建、模型建立、路由、装饰器等使用,虽然都说flask是很轻量级很快的框架,但是毕竟能力尚浅还没有具体感受到其中的重点,但是简单的功能开发已经可以实现了,后期还有包括蓝图、缓存机制、异步等都只能等之后慢慢在项目中摸索了,实验室新任务必须转到sanic去了,所以Flask的学习得先放一阵子了,这里简单总结下,并把网易云课堂里面的案例给大家展示一下

    案例

    1. 项目结构


      image.png
    2. 模型(models.py)
      models里面主要是模型的建立,用户模型、问答模型和评论模型,重点在于外键和反向关联这一块,模型的迁移以及表更新的代码块都在manage.py内
    from exts import db
    from datetime import datetime
    
    class User(db.Model):
        __tablename__ = 'user'
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        telephone = db.Column(db.String(11), nullable=False)
        username = db.Column(db.String(50), nullable=False)
        password = db.Column(db.String(100), nullable=False)
    
    
    class Question(db.Model):
        __tablename__ = 'question'
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        title = db.Column(db.String(50), nullable=False)
        content = db.Column(db.Text, nullable=False)
        create_time = db.Column(db.DateTime, default=datetime.now)
        author_id = db.Column(db.Integer,db.ForeignKey('user.id'))
        author = db.relationship('User', backref=db.backref('questions'))
    
    class Comment(db.Model):
        __tablename__ = 'comment'
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        content = db.Column(db.Text, nullable=False)
        question_id = db.Column(db.Integer, db.ForeignKey('question.id'))
        create_time = db.Column(db.DateTime, default=datetime.now)
        author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
        author = db.relationship('User', backref=db.backref('comments'))
        question = db.relationship('Question', backref=db.backref('comments'), order_by=create_time.desc())
    
    1. 配置(config.py)

    配置文件都单独出来,里面主要是数据库连接上的配置,数据库还是使用的mysql数据库,使用pymysql连接

    import os
    import pymysql
    
    SECRET_KEY = os.urandom(24)
    SQLALCHEMY_DATABASE_URI ='mysql+pymysql://root:299521@127.0.0.1:3306/flask_test'
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    
    1. 扩展包(exts.py)

    exts里面对db进行初始化,放置主文件与models文件相互调用产生异常

    from flask_sqlalchemy import SQLAlchemy
    
    db = SQLAlchemy()
    
    1. 包管理(manage.py)

    重点是要引入模型和app以及对命令的添加,执行迁移时一定记得父命令(db)

    from flask_script import Manager
    from flask_migrate import Migrate, MigrateCommand
    from flask_test import app
    from exts import db
    import pymysql
    from models import User, Question
    
    manager = Manager(app)
    migrate = Migrate(app, db)
    manager.add_command('db', MigrateCommand)
    
    
    if __name__ == '__main__':
        manager.run()
    
    
    1. 装饰器(decorators.py)

    这里涉及到对登录的验证,所以自定义了装饰器,对装饰器不太熟悉的话建议去看看文档

    from functools import wraps
    from flask import session
    from flask import redirect, url_for
    
    def login_required(func):
    
        @wraps(func)
        def wrapper(*args, **kwargs):
            if session.get('user_id'):
                return func(*args, **kwargs)
            else:
                return redirect(url_for('login'))
        return wrapper
    
    1. 主文件(flask_test.py)

    主要代码块里面重点在于对表单数据的提取,GET、POST请求的差异,其它诸如url_for,模板渲染都相对基础,session的设置和路由参数指定也可以详细看一下

    from flask import Flask, render_template, request, session, url_for, redirect
    import config
    from decorators import login_required
    import pymysql
    from exts import db
    from models import User, Question, Comment
    
    
    
    app = Flask(__name__)
    app.config.from_object(config)
    db.init_app(app)
    
    
    
    
    @app.route('/')
    def index():
        context = {
            'questions': Question.query.order_by('-create_time').all()
        }
        return render_template('index.html', **context)
    
    @app.route('/detail/<question_id>/')
    def detail(question_id):
        question_model = Question.query.filter(Question.id == question_id).first()
    
        return render_template('detail.html', question = question_model)
    
    
    @app.route('/comment/', methods=['POST'])
    @login_required
    def comment():
        content = request.form.get('content')
        question_id = request.form.get('question_id')
    
        comment = Comment(content=content)
        user_id = session.get('user_id')
        user = User.query.filter(User.id==user_id).first()
        comment.user = user
        question = Question.query.filter(Question.id==question_id).first()
        comment.question = question
        db.session.add(comment)
        db.session.commit()
        return redirect(url_for('detail', question_id=question_id))
    
    
    @app.route('/login/', methods=['GET', 'POST'])
    def login():
        if request.method == 'GET':
            return render_template('login.html')
        else:
            telephone = request.form.get('telephone')
            password = request.form.get('password')
            user = User.query.filter(User.telephone == telephone, User.password == password).first()
            if user:
                session['user_id'] = user.id
                session.permanent = True
                return redirect(url_for('index'))
            else:
                return '登录失败'
    
    @app.route('/register/', methods=['GET', 'POST'])
    def register():
        if request.method == 'GET':
            return render_template('register.html')
        else:
            telephone = request.form.get('telephone')
            username = request.form.get('username')
            password1 = request.form.get('password1')
            password2 = request.form.get('password2')
            if User.query.filter(User.telephone == telephone).first():
                return '当前号码已注册'
            else:
                if User.query.filter(User.username == username).first():
                    return 'username已注册'
                else:
                    if password1 == password2:
                        user = User(username=username, telephone=telephone, password=password2)
                        db.session.add(user)
                        db.session.commit()
                        return redirect(url_for('login'))
                    else:
                        return '密码不符合'
    
    @app.route('/logout/' )
    def logout():
        session.pop('user_id')
        return redirect(url_for('login'))
    
    @app.route('/push_article/', methods=['GET', 'POST'] )
    @login_required
    def push_article():
        if request.method == 'GET':
            return render_template('push.html')
        else:
            title = request.form.get('title')
            content = request.form.get('content')
            question = Question(title=title, content=content)
            user_id = session.get('user_id')
            user = User.query.filter(User.id==user_id).first()
            question.author = user
            db.session.add(question)
            db.session.commit()
            return redirect(url_for('index'))
    
    @app.context_processor
    def has_user():
        user_id = session.get('user_id')
        if user_id:
            user = User.query.filter(User.id == user_id).first()
            if user:
                return {'user':user}
            else:
                return {}
        else:
            return {}
    
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    总结

    总体来说,案例很简单,综合考察了之前所总结的所有小模块的功能,最后结合Bootstrap一起做了一个简易博客的小案例,页面其实不用太过在意,重点关注与后台实现,大家不熟悉的话建议尝试一下这个案例

    -完整代码详情参考Github或者网易云课堂

    相关文章

      网友评论

        本文标题:Flask学习(十一) - 阶段总结&案例

        本文链接:https://www.haomeiwen.com/subject/iddiqqtx.html