美文网首页
Python-Flask框架

Python-Flask框架

作者: 云中的Jason | 来源:发表于2018-10-16 21:49 被阅读0次

    (本文后期会重新整理,敬请期待)

    URL和视图

    安装Homebrew

    在终端输入以下代码,安装Homebrew:

    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    

    Python安装

    mac环境下默认安装了python 2.7,安装3.6需要用以下代码:

    brew install python3
    

    Python虚拟环境安装

    1. 因为python的框架版本更新迭代速度太快,有时需要在一台电脑上存在一个框架的多个版本,这时就需要虚拟环境。通过以下代码安装:
    pip3 install virtualenv
    
    1. 虚拟环境管理工具virtualenvwrapper可以很便捷的新建、删除、切换虚拟环境。virturalenvwrapper可以通过一下代码安装:
    pip3 install virtualenvwrapper
    
    1. 在使用virturalenvwrapper之前,需要对 virtualenvwrapper 进行配置。它需要指定一个环境变量,叫做 WORKON_HOME,并且需要运行一下它的初始化工具 virtualenvwrapper.sh,这个脚本默认安装在 /usr/local/bin/ 目录下。WORKON_HOME 就是它将要用来存放各种虚拟环境目录的目录,这里我们可以设置为 ~/.Python/Envs。通过以下方式将配置代码加入.bash_profile中
    修改方式
    vim .bash_profile
    open -e .bash_profile
    
    配置代码
    export WORKON_HOME=$HOME/.Python/Envs
    export VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python3
    source /usr/local/bin/virtualenvwrapper.sh 
    
    1. virtualenvwrapper常用指令:
    mkvirtualenv env1 //创建虚拟环境
    workon //列出虚拟环境
    workon Flask_env //使用虚拟环境env1
    deactivate //退出虚拟环境
    rmvirtualenv env1 //删除虚拟环境env1
    

    flask 安装

    进入创建的虚拟环境,在虚拟环境下安装flask,安装指令如下:

    pip3 install flask
    

    第一个flask程序

    from flask import Flask
    app = Flask(__name__)
    @app.route('/')
    def hello_world():
        return 'Hello world!'
    if __name__ == '__main__'
        app.run()
    

    debug 模式

    1. 在app.run()中传入一个关键字参数debug,app.run(debug=Ture),就设置当前项目为debug模式。
    2. debug模式的两大功能:
    • 当程序出现问题时,可以在页面中看到错误信息和出错的位置。
    • 只要修改了项目中的Python文件,程序会自动加载,不需要手动重启服务器。

    使用配置文件

    1. 新建一个'config.py'文件
    2. 在主app文件中导入这个文件,并且配置到app中,示例代码如下
    import config
    app.config.from_object(config)
    
    1. 还有许多的其他参数,都是放在这个配置文件中,比如‘SECRET_KEY‘和’SQLALCHEMY‘。

    URL 传参

    1. 参数的作用:可以在相同的URL中指定不同的参数,来加载不同的数据。
    2. 在flask中使用参数:
    @app.route('/article/<id>')
    def article(id):
        return u'你请求的参数是:%s' % id
    * 参数需要放在两个尖括号中
    * 视图函数中需要放和url中的参数同名的参数
    

    URL 反转

    1. 什么叫反转URL:从视图函数到URL的转换叫做反转URL
    href="{{ url_for('index') }}"
    
    1. 反转URL的用处
    • 在页面重定向的时候,会使用URL反转
    • 在模版中,也会使用URL反转

    页面跳转和重定向

    1. 用处:在用户访问一些需要登录的界面时,如果用户没有登录,那么可以让它重定向到登录页面
    2. 代码实现:
    from flask import Flask,redirect,url_for
    redirect(url_for('login'))
    

    Jinjia2模版

    Flask渲染Jinjia2模版和传参

    1. 如何渲染模版
      • 模版放在‘templates’文件夹下
      • 从‘flask’中导入‘render_template’函数
      • 从视图函数中,使用‘render_template’函数,渲染模版。注意,只需要填写模版的名字,不需要填写‘templates’这个文件路径
    2. 模版传参:
      • 如果只有一个或少量参数,直接在‘render_template’函数中添加关键字参数就可以了。
      • 如果有多个参数,那么可以先把所有的参数放到字典中,然后在‘render_template’中,使用**将字典转换成关键参数传递进去,这样的代码更方便管理和使用。
    3. 在模版中,使用一个变量的语法是{{ params }}
    4. 访问模版中的属性或是字典,可以通过{{ params.property }}的形式,或者使用{{ params['property'] }}

    if判断语句

    1. 语法
    {% if xxx %}
    {% eles %}
    {% endif %}
    
    1. if的使用和python相差无几

    for循环遍历

    1. 字典的遍历语法和python一样,可以使用‘items()’、‘keys()’、‘values()’、‘iteritems()’、‘iterkeys()’、‘itervalues()’
    {% for k,v in user.items() %}
        <p>{{ k }}:{{ v }}</p>
    {% endfor %}
    
    1. 列表的遍历与python一样
    {% for website in websites %}
        <p>{{ website }}</p>
    {% endfor %}
    

    过滤器

    1. 介绍和语法
    • 介绍:过滤器可以处理变量,把原始的变量经过处理后再展示出来,作用的对象是变量
    • 语法:
    {{ params|default('xxx') }}
    
    1. default过滤器:如果当前变量不存在,这时候可以指定默认值
    2. length过滤器:求列表、字符串、字典和元祖的长度
    {{ params|length }}
    

    继承和block

    1. 继承的作用和语法
    • 作用:可以把公共的代码放在父模版中,避免每一个模版写同样的代码
    • 语法:
    {% extends 'base.html' %}
    
    1. block实现:
    • 作用:可以让子模版实现自己的需求,父模版需要提前定义
    <!--接口-->
    {% block main %}{% endblock%}
    
    • 注意点:子模版中的代码必须放在block块中
    {% block main %}
        <h1>这是登录页面</h1>
    {% endblock %}
    

    URL链接和加载静态文件

    1. 使用‘url_for(视图函数名称)’可以反转成url
    2. 加载静态文件:
    • 语法:‘url_for('static',filename='路径')’
    • flask会从‘static’文件夹中开始寻找,不需要写‘static’这个路径
    • 可以加载css、js、image文件
    <link href="{{ url_for('static',filename='css/static.css') }}" rel="stylesheet" type="text/css" />
    <script src="{{ url_for('static',filename='js/static.js') }}"></script>
    

    SQLAlchemy数据库

    Mac下数据库的安装

    1. MySql下载链接
    2. Mac上安装Mysql后,在系统偏好设置里启动MySql服务
    3. 配置环境变量:
    • 进入/usr/local/mysql/bin,查看此目录下是否有mysql
    • 执行以下指令:
    进入vim
    vim ~/.bash_profile
    添加mysql路径
    PATH=$PATH:/usr/local/mysql/bin
    按esc,输入‘:wq’保存退出
    激活配置文件
    source ~/.bash_profile
    
    1. 数据库相关指令:
    mysql -u username -p
    show databases
    

    mysqlclient安装

    1. 进入虚拟环境,安装mysql-connector-c
    brew install mysql-connector-c
    
    1. 修改mysql_config文件的配置,位于/usr/local/bin/mysql_config
    原代码:
    libs="-L$pkglibdir"
    libs="$libs -l "
    
    更改后代码:
    libs="-L$pkglibdir"
    libs="$libs -lmysqlclient -lssl -lcrypto"
    
    1. 安装mysqlclient:
    pip3 install mysqlclient
    

    Flask-SQLAlchemy的介绍与安装

    1. ORM:Object Relationship Mapping(模型关系映射)
    2. flask-sqlalchemy是一套ORM框架
    3. ORM的好处:可以让我们操作数据库和操作对象一样,非常方便。因为一个表就抽象成一个类,一条数据就抽象成该类的一个对象。
    4. 安装‘Flask-sqlalchemy’:
    pip install flask-sqlalchemy
    

    Flask-SQLAlchemy的使用

    1. 初始化和设置数据库配置信息:
    • 使用flask_sqlalchemy中的SQLAlchemy进行初始化:
    from flask_sqlalchemy import SQLAlchemy
    app = Flask(__name__)
    db = SQLAlchemy(app)
    
    1. 设置配置信息,在config.py文件中添加以下配置信息:
    * dialect+driver://username:password@host:port/database *
    DIALECT = 'mysql'
    DRIVER = 'mysqldb'
    USERNAME = 'root'
    PASSWORD = 'Gao123456'
    HOST = 'localhost'
    PORT = '3306'
    DATABASE = 'db_demo1'
    SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE)
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    
    1. 在主app文件中添加配置文件(config.py)
    • 配置文件和主app文件在同一目录下:
    import config
    
    app.config.from_object(config)
    
    • 配置文件来自于其他目录(./config/config.py)
    目录需要包含一个叫做 __init__.py 的文件
    from config.config
    
    app.config.from_object(config.config_demo1)
    
    1. 测试
    db.creat_all()
    如果没有报错,说明配置没有问题,如果有错误,可以根据错误进行修改
    

    SQLAlchemy模型与表映射

    1. 模型需要继承自‘db.Model’,然后需要映射到表中的属性,必须写成‘db.Column’的数据类型。
    2. 数据类型:
    • db.Integer:int
    • db.String:varchar()
    • db.Text:text
    1. 其他参数:
    • Primary_key:代表将这个字段设置为主键
    • autoincrement:代表这个主键为自增长
    • nullable:代表这个字段是否为空,默认为空。可以将这个值设置为‘False’,那么在数据库中,这个值就不能为空了。
    • 最后需要调用‘db.create_all()’来讲模型真正的创建到数据库中。
    class Article(db.Model):
        __tablename__ = 'article'#指定表名
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        title = db.Column(db.String(100),nullable=False)
        content = db.Column(db.Text,nullable=False)
    

    SQLAlchemy数据增删改查

    1. 增加
    # 增加
    article1 = Article(title='aaa',content='bbb')
    db.session.add(article1)
    # 事务
    db.session.commit()
    
    1. 查找
    # 查询
    article1 = Article.query.filter(Article.title == 'aaa').first()
    print('title:%s' % article1.title)
    print('comment:%s' % article1.content)
    
    1. 修改
    # 修改
    # 1.先把需要修改的数据查找出来
    article1 = Article.query.filter(Article.title == 'aaa').first()
    # 2.将查找到的数据所要修改的地方进行修改
    article1.title = 'new title'
    # 3.做事务提交
    db.session.commit()
    
    1. 删除
    # 删除
    # 1.把需要删除的数据查找出来
    article1 = Article.query.filter(Article.title == 'aaa').first()
    # 2.删除数据
    db.session.delete(article1)
    # 3.做事务提交
    db.session.commit()
    

    Flask_SQLAlchemy外键及其关系

    1. 外键:
    class User(db.Model):
        __tablename__ = 'user'
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        username = db.Column(db.String(100),nullable=False)
    
    class Article(db.Model):
        __tablename__ = 'article'
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        title = db.Column(db.String(100),nullable=False)
        content = db.Column(db.Text,nullable=False)
        author_id = db.Column(db.Integer,db.ForeignKey('user.id'))
        author = db.relationship('User',backref=db.backref('articles'))
    
    1. author = db.relationship('User',backref=db.backref('articles'))解释:
    • 给‘Article’这个模型添加一个‘author’属性,可以访问这篇文章的作者的数据,就像访问普通模型一样
    • ‘backref’是定义反向引用,可以通过‘User.articles’访问这个模型所写的所有文章
    1. 多对多关系
    • 多对多的关系,要通过一个中间表进行关联
    • 中间表,不能通过‘class’的方式创建,只能通过‘db.Table’的方式创建
    class Article(db.Model):
        __tablename__ = 'article'
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        title = db.Column(db.String(100),nullable=False)
        tags = db.relationship('Tag',secondary='article_tag',backref=db.backref('articles'))
    
    class Tag(db.Model):
        __tablename__ = 'tag'
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        name = db.Column(db.String(100),nullable=False)
    
    article_tag = db.Table('article_tag',
        db.Column('article_id',db.Integer,db.ForeignKey('article.id'),primary_key=True),
        db.Column('tag_id',db.Integer,db.ForeignKey('tag.id'),primary_key=True)
    )
    
    • 设置关联:
    tags = db.relationship('Tag',secondary='article_tag',backref=db.backref('articles'))
    
    • 访问和添加数据可以通过一下方式操作:
    • 添加数据
    article1 = Article(title='iPhone')
    article2 = Article(title='iPad')   
    tag1 = Tag(name='Easy')
    tag2 = Tag(name='Good')
    article1.tags.append(tag1)
    article1.tags.append(tag2)
    article2.tags.append(tag1)
    article2.tags.append(tag2)
    db.session.add(article1)
    db.session.add(article2)
    db.session.add(tag1)
    db.session.add(tag2)
    db.session.commit()
    
    • 访问数据
    article1 = Article.query.filter(Article.title =='iPhone').first()
    tags = article1.tags
    for tag in tags:
        print (tag.name)
    

    Flask_script的介绍与安装

    1. Flask-script:其作用是可以通过命令行的形式来操作FLask。例如通过命令跑一个开发版本的服务器,设置数据库,定时任务等。
    2. 安装:进入到虚拟环境中,使用一下命令安装:
    pip install flask-script
    
    1. 如何直接在主‘manager.py’中写命令,那么在终端只需要python manager.py command_name就可以了。
    2. 如果把一些命令集中在一个文件中,那么在终端就需要输入一个父命令,比如python manager.py db init
    3. 例子:
    from flask_script import Manager
    from flask_script_demo import app
    from db_script import DBmanager
    
    manager = Manager(app)
    
    @manager.command
    def runserver():
        print('The server is running!')
    
    manager.add_command('db',DBmanager)
    
    if __name__ == '__main__':
        manager.run()
    
    1. 有子命令的例子:
    from flask_script import Manager
    
    DBmanager = Manager()
    
    @DBmanager.command
    def init():
        print('数据库初始化完成')
    
    @DBmanager.command
    def migrate():
        print('数据库迁移成功')
    

    分开‘models’以及解决循环引用:

    1. 分开models的目的:为了让代码更加方便的管理
    2. 如何解决循环引用:把‘db’放在一个单独的文件中,切断循环引用的线条就可以了
    # models_sep.py
    from flask import Flask
    from models import Article
    from exts import db
    
    # models.py
    from exts import db
    class Article(db.Model):
        pass
    
    # exts.py
    from flask_sqlalchemy import SQLAlchemy
    db = SQLAlchemy()
    
    db.init_app(app)
    

    Flask-Migrate的介绍与安装

    1. 介绍:因为采用db.create_all在后期修改字段的时候,不会自动的映射到数据库中,必须删除表,然后重新运行db.create_all才会重新映射,这样不符合我们的需求。因此flask—migrade就是为了解决这个问题,它可以在每次修改模型后,将修改的内容映射到数据库中
    2. 安装:进入虚拟环境使用一下命令安装:
    pip install flask-migrate
    
    1. 使用‘flask-migrate’必须借助‘flask-script’,这个包的‘MigrateCommand’中包含的所有与数据库相关的命令
    2. ‘flask-migrate’相关的命令:
    • python manager.py db init:初始化一个迁移脚本环境,只需要执行一次
    • python manager.py migrate:将模型生成迁移文件,只要模型更改了,就需要执行一边这个命令
    • python manager.py db upgrade:将迁移文件真正的映射到数据库中,每次运行了migrate命令后,就要运行此命令
    1. 注意点:需要映射到数据库的模型,都要导入到manager.py中,如果没有导入,就不会映射到数据库中
    2. manager.py相关代码:
    from flask_script import Manager
    from migrate_demo import app
    from flask_migrate import Migrate,MigrateCommand
    from exts import db
    from models import Article
    
    # 模型 -> 迁移文件 -> 表
    # init
    # migrate
    # upgrate
    
    manager = Manager(app)
    
    # 1. 要使用Flask-migrate,必须要绑定app和db
    migrate = Migrate(app,db)
    # 2. 把MigrateCommand命令添加到manager中
    manager.add_command('db',MigrateCommand)
    
    if __name__ == '__main__':
        manager.run()
    

    session和cookie操作

    cookie的相关内容:

    1. cookie出现的原因:在网站中,http请求是无状态的。这就是说即使第一次和服务器连接并且登录成功后,第二次请求服务器依然不能知道当前请求的是哪个用户。cookie的出现就是为了解决这一问题,第一次登录后,服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地。当用户发送第二次请求的时候,就会自动的把上次请求存储的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪一个了
    2. 如果服务器返回了cookie给浏览器,那么浏览器再次请求相同的服务器的时候,就会自动的吧cookie发送给服务器,这个过程用户不需要处理
    3. cookie是保存在浏览器中的,相对的是浏览器

    session的相关内容:

    1. session介绍:session和cookie的作用有点类似,都是为了存储用户相关的信息。不同的是,cookie是存储在本地浏览器,而session存储在服务器。存储在服务器的数据会更加安全,不容易被窃取。但存储在服务器也有一定的弊端,就是会占用服务器的资源,但是服务器发展至今,一些session信息还是绰绰有余的
    2. 使用session的好处:
    • 敏感数据不是直接发送回浏览器,而是发送回一个session_id,服务器将session_id和敏感数据做一个映射存储在session(服务器上)中,更加安全
    • session可以设置过期时间,也保证了用户的账号安全

    Flask中的session工作机制

    1. flask中session机制是:把敏感数据经过加密后放入session中,然后再把session存放到cookie中。下次请求的时候,再从浏览器发送过来的cookie中
      读取session,然后从session中读取敏感数据并进行解密,最终获取到用户数据
    2. flask的这种session机制,可以节省服务器的开销,因为把所有的信息都存储到了客户端(浏览器)
    3. 安全是相对的,把session放到cookie中,经过加密也是比较安全的

    Flask中操作session

    1. 使用session需要从flask中导入session,以后所有和session相关的操作都是通过这个变量来的
    2. 使用session需要设置‘SECRET_KEY’用来加密,并且这个‘SECRET_KEY’如果在每次服务器启动后都变化的话,那么之前的session就不能再通过当前这个‘SECRET_KEY’进行解密了
    3. 操作session的时候和操作字典相同
    • 添加:session['username']
    • 删除:session.pop('username')或者del session['username']
    • 获取:session.get('username')
    • 清除所有session:session.clear()
    1. 设置session的过期时间
    • 如果没有指定session的过期时间,那么默认是浏览器关闭后就自动结束
    • 如果设置了session的permanent属性为True,那么过期时间默认为31天
    • 可以通过设置:app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)来更改过期时间

    装饰器

    1. 装饰器实际上就是一个函数,有两个特别之处
    • 参数是一个函数
    • 返回值是一个函数
    1. 装饰器的使用是通过@符号,放在函数的上面
    2. 装饰器中定义的函数,要使用args,*kwargs两个参数组合
    3. 需要使用functools.wraps在装饰器中的函数上把传进来的函数进行一个处理,这样就不会丢失其原来name等属性
    from functools import wraps
    def my_log(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            print('hello world!')
            func(*args, **kwargs)
        return wrapper
    
    @my_log
    def run():
        print('run')
    
    @my_log
    def add(a, b):
        c = a + b
        print('c = %s' % c)
    
    run()
    add(1, 3)
    print(run.__name__)
    

    知识点补充

    get请求和post请求

    1. get请求
    • 使用场景:如果只对服务器获取数据,并没有对服务器产生任何影响,那么这时候使用get请求
    • 传参:get请求传参是放在url中,并且是通过'?'的形式来指定key和value的
    1. post请求
    • 使用场景:如果要对服务器产生影响,那么使用post请求
    • 传参:post请求传参不是放在url中,是通过‘form data’的形式发送给服务器的

    get和post请求获取参数

    1. get请求是通过flask.request.args来获取的
    2. post请求是通过flask.request.form来获取的
    3. post请求在模版中要注意:
    • input标签中要写name来标示这个value的key,方便后台获取
    • 在写form表单的时候,要指定method='post',并且要指定action="{{ url_for('login') }}"
    1. 示例代码
    <form action="{{ url_for('login') }}" method="POST">
        <table>
            <tbody>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" placeholder="请输入用户名" name="username"></td>
                </tr>
                <tr>
                    <td>密码:</td>
                    <td><input type="text" placeholder="请输入密码" name="password"></td>
                </tr>
                <tr>
                    <td></td>
                    <td><input type="submit" value="登录"></td>
                </tr>
            </tbody>
        </table>
    </form>
    

    保存全局变量的g属性(g:global)

    1. g对象是专门用来保存用户的数据的
    2. g对象在一次请求中,代码所有的地方都是可以使用的

    钩子函数(hook)

    1. before_request:
    • 在请求之前执行
    • 是在视图函数执行之前执行的
    • 这个函数只是一个装饰器,它可以把需要设置为钩子函数的代码放到视图函数执行之前执行
    • 代码示例:
    @app.before_request
    def my_before_request():
       if session.get('username'):
           g.username = session.get('username')
    
    1. context_processor:
    • 上下文处理器应该返回一个字典,字典中的‘key’会被模版当作变量来渲染
    • 上下文处理器中返回的字典,在所有页面中都是可用的
    • 被这个装饰器修饰的钩子函数,必须要返回一个字典,即使为空也要返回
    • 代码示例:
    @app.context_processor
    def my_context_processor():
        return {'username':'Jason'}
    

    实战演练

    项目结构搭建

    • zlktqa.py:主app文件
    • config.py:配置文件,设置数据库、密钥、debug等等
    • exts.py:解决循环引用
    • manager.py:flask_script命令应用
    • models.py:分开models

    导航条构建

    • UI框架网站bootstrap
    • BootCDN导入jQuery
    • head标签中引入bootstrp的css、jquery和js文件

    父模版抽离

    {% extends 'base.html' %}
    {% block title %}首页{% endblock %}
    {% block main %}这是首页{% endblock %}
    

    登录页面完成和注册页面完成

    pass

    用户模型创建

    1. 创建模型User
    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)
    
    1. 进入虚拟环境,利用flask-script创建数据库表
    python manage.py db init
    python manage.py db migrate
    python manage.py db upgrade
    

    注册功能完成

    • 注册功能未判断输入是否为空以及是否符合相应格式
    • 密码在数据库中为明文

    登录功能完成

    待完善

    登录和注销状态切换

    利用钩子函数context_processor

    发布问答界面完成

    登录限制

    在未登录状态下,访问发布问答页面时,要登录

    from functools import wraps
    from flask import session, redirect
    # 登录限制的装饰器
    def login_required(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if session.get('user_id'):
                return func(*args, **kwargs)
            else:
                return redirect('login')
        return wrapper
    
    # 发布问答
    @app.route('/question/')
    @login_required
    def question():
        if request.method == 'GET':
            return render_template('question.html')
        else:
            pass
    

    发布问答功能完成

    # 发布问答
    @app.route('/question/', methods=['GET', 'POST'])
    @login_required
    def question():
        if request.method == 'GET':
            return render_template('question.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'))
    

    密码保护

    from exts import db
    # 导入转换密码需要的库
    from werkzeug.security import generate_password_hash, check_password_hash
    
    
    # 用户模型
    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_hash = db.Column(db.String(255), nullable=False)
    
    
    # 定义函数,需要用属性时,可以用函数代替
        @property
        def password(self):
            return self.password_hash
    
    
    # 转换密码为hash存入数据库
        @password.setter
        def password(self, row_password):
            self.password_hash = generate_password_hash(row_password)
    
    
    # 检查密码
        def check_password(self, row_password):
            return check_password_hash(self.password_hash, row_password)
    
    
    # 登录
    @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).first()
            if user:
                if user.check_password(password):
                    session['user_id'] = user.id
                    session.permanent = True
                    return redirect(url_for('index'))
                else:
                    return u'密码错误!'
            else:
                return u'用户不存在,请注册后登录!'
    
    
    # 注册
    @app.route('/regist/', methods=['GET', 'POST'])
    def regist():
        if request.method == 'GET':
            return render_template('regist.html')
        else:
            telephone = request.form.get('telephone')
            username = request.form.get('username')
            password_1 = request.form.get('password_1')
            password_2 = request.form.get('password_2')
            # 手机号码验证,如果被注册,就不能再注册了
            user = User.query.filter(User.telephone == telephone).first()
            if user:
                return u'改手机号已被注册,请更换手机号码!'
            else:
                # password_1和password_2要一样才可以
                if password_1 != password_2:
                    return u'两次密码不一样,请核对后再填写!'
                else:
                    user = User(telephone=telephone, username=username, password=password_1)
                    db.session.add(user)
                    db.session.commit()
                    # 如果注册成功,就让页面跳转到登录界面
                    return redirect(url_for('login'))
    

    定时任务Celery

    1. 安装celery
    pip install celery
    
    1. 通过Homebrew安装消息代理Redis
    brew install redis
    
    1. 通过指令redis-server启动Redis(关闭redis:redis-cli shutdown
    2. 通过终端进入celery文件所在目录,执行以下命令开启工作池
    celery -A celery_task worker --loglevel=info
    

    celery_task代码如下所示

    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    from celery import Celery
    from celery import platforms
    from crawler import getdata
    import datetime
    import time
    
    
    # 用于开启root也可以启动celery服务,默认是不允许root启动celery的
    platforms.C_FORCE_ROOT = True
    # 创建一个celery实例,传递进去的第一个参数必须是本文件的文件名celery,指定broker为本机redis6380服务
    celery = Celery('celery_task', broker='redis://localhost:6379/0')
    
    
    @celery.task
    def task(h=1, m=0):
        while True:
            while True:
                now = datetime.datetime.now()
                if now.hour == h and now.minute == m:
                    break
                time.sleep(60)
            getdata()
            print('执行完毕!')
    
    

    相关文章

      网友评论

          本文标题:Python-Flask框架

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