zoukankan      html  css  js  c++  java
  • Flask框架

    #从flask这个框架中导入Flask这个类
    from flask import Flask

    # 初始化一个Flask对象
    # 需要传递一个参数__name__
    # 1.方便flask框架寻找资源
    # 2.方便flask插件比如Flask-Sqlalchemy出现错误的时候,好去寻找问题所在的位置
    app = Flask(__name__)

    # @app.route是一个装饰器
    # @开头,并且在函数的上面,说明是装饰器
    # 这个装饰器的作用是,做一个url与视图函数的映射
    # 127.0.0.1:5000/ -->去请求hello_world函数,然后将结果返回给浏览器
    @app.route('/')
    def hello_world():
        return 'Hello World!'

    #如果当前这个文件是做为入口程序运行,那么就执行app.run()
    if __name__ == '__main__':
        # app.run()
        # 启动一个应用服务器,来接受用户的请求
        # while True:
        #   listen()
        app.run()

     

    ### 设置debug模式

    app.run(debug=True)

    Debug 模式两大功能

    * 当程序出现问题的时候,可以在页面中看到错误信息和出错位置

    * 只要修改了项目中的.py文件,程序会自动加载,不需要手动重新启动服务器

     

    ### 使用配置文件

    1. 新建一个config.py文件

    2. 在主app文件中导入这个文件,并且配置到’app’中

    示例代码如下

    ```

    import config
    app.config.from_object(config)

    ```

     

    ### url传参数

    1. 参数的作用: 可以在相同的URL,但是指定不同的参数,来加载不同的数据

    2. 在flask中如何使用参数

    ```

    @app.route('/article/<id>')
    def article(id):
        return '您请求的参数是: %s' %id

    * 参数需要放在<>中

    * 视图函数中需要放和url中的同名的参数

    ```

     

    ### 反转URL

    1. 什么叫做反转URL: 从视图函数到url的转换叫做反转url

    2. 反转url的好处:

      * 在页面重定向的时候,会使用url反转

      * 在模板中,也会使用url反转

    代码示例:

    @app.route('/')
    defindex():
        print(url_for('my_list'))
        print(url_for('article',id='abc'))
        return'Hello World!123'

    @app.route('/list/')

    def my_list():
        return 'list'

    @app.route('/article/<id>')

    defarticle(id):
        return'您请求的参数是: %s' %id

     

     

    ### 页面跳转和重定向

    1. 用处: 在用户访问一些需要登录的页面的时候,如果用户没有登录,那么可以让他重定向到登录页面

    @app.route('/')
    defindex():
        login_url=url_for('login')
        returnredirect(login_url)
        return'这是首页'

    @app.route('/login/')

    deflogin():
        return'这是登录页面'

     

     

    ### 模板渲染和参数传递

    1.如何渲染模板:

      * 模板放在`templates`文件夹下

      * 从`flask`中导入`render_template`函数

      * 在视图函数中,使用`render_template`函数,不需要填写template路径

     @app.route('/')
    defindex():
        return render_template('index.html')

    2.模板传参:

    * 如果只有一个或少量参数

     return render_template('index.html',username=’mike’)

    * 如果有多个参数的时候,那么可以把所有参数放在字典中

    @app.route('/')
    def index():
        context={
            'username' : '瞿诗寒',
            'sex' : '男',
            'age' : 18
        }
        return render_template('index.html',**context)

    * 在模板中,如果要使用一个变量,语法`{{params}}`

    * 访问模型中的属性或者是字典,可以通过`{{websites.baidu}} `或者`{{websites[‘baidu’]}}`

     

    ### if判断语句

    Jinja2

    {% if user and user.age>19 %}
        <a href="#">{{ user.username }}</a>
        <a href="#">注销</a>
    {% else %}
        <a href="#">登录</a>
        <a href="#">注册</a>
    {% endif %}

     

    ### for循环遍历列表和字典

    语法和python一样可以用 items() keys() values() iteritems() iterkeys() itervalues()

    <table>
        <thead>
            <th>书名</th>
            <th>作者</th>
            <th>价格</th>
        </thead>
        <tbody>
            {% for book in books %}
                <tr>
                    <td>{{ book.name }}</td>
                    <td>{{ book.author }}</td>
                    <td>{{ book.price }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>

     

    @app.route('/')
    def index():
        books=[
            {
                'name': '西游记',
                'author': '吴承恩',
                'price': 100
            },
            {
                'name': '红楼梦',
                'author': '曹雪芹',
                'price': 200
            },
            {
                'name': '三国演义',
                'author': '罗贯中',
                'price': 300
            },
            {
                'name': '水浒传',
                'author': '施耐庵',
                'price': 130
            }
        ]
        return render_template('index.html',books=books)

     

    ### 过滤器

    作用的对象是模板中的变量{{param}}

    * 介绍: 过滤器可以处理变量,把原始的变量经过处理后再展示出来

    语法:{{ avatar|default('https://ss1.bdstatic.com/fm=27&gp=0.jpg') }}

     * default过滤器: 如果当前变量不存在,这时候可以指定默认值

     * length过滤器: 求列表或字符串或者字典或者元组的长度

    @app.route('/')
    def index():
        comments=[
            {
                'user':'mike',
                'content': '123123'
            },

            {
                'user': 'mike',
                'content': '123123'
            }

        ]
        return render_template('index.html',comments=comments)

     

    <p>评论数:({{ comments|length }})</p>
    <ul>
        {% for comment in comments %}
            <li>
                <a href="#">{{ comment.user }}</a>
                <p>{{ comment.content }}</p>
            </li>
        {% endfor %}
    </ul>

     

    ### 继承和block: 参见flaskstu3

    1. 继承作用和用法

    * 作用: 可以把一些公共的代码放在父模板中,避免每个模板写同样的代码

    * 语法

    {% extends 'base.html' %}

    2. block实现  

    * 作用: 可以让子模版实现一些自己的需求,父模板提前定义好

    * 注意点: 子模版中的代码,必须放在block块中

     

    ### url链接: 参见flaskstu4

    <a href="{{ url_for('login') }}">登录</a>

     

    ### 加载静态文件: 参见flaskstu4

    1. 语法

    加载css文件

    <link rel="stylesheet" href="{{ url_for('static',filename='css/index.css') }}"/>

    加载 js文件

    <script src="{{ url_for('static',filename='js/index.js') }}"></script>

    加载 image文件

    <img src="{{ url_for('static',filename='images/1.jpg') }}" alt=""/>

    2. 静态文件 flask 会从static 文件夹中开始寻找,所以不需要再写’static’这个路径了

    3. 可以加载 css js image文件

     

    Flask-SQLAlchemy的安装介绍

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

    ### Flask-SQLAlchemy使用

    1.初始化和设置数据库配置信息

    *使用flask_sqlalchemy中的SQLALchemy进行初始化:

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    import config
    app = Flask(__name__)
    app.config.from_object(config)
    db=SQLAlchemy(app)

    2.设置配置信息

    在config.py文件中添加以下配置信息

    # dialect+driver://username:password@host:post/database
    DIALECT = 'mysql'
    DRIVER = 'mysqldb'
    USERNAME = 'root'
    PASSWORD = 'root'
    HOST = '127.0.0.1'
    PORT = '3306'
    DATABASE = 'db_demo1'
    SQLALCHEMY_DATABASE_URI="{}+{}://{}:{}@{}:{}/{}".format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE)

     

    ### 使用Flask-SQLAlchemy创建模型与表的映射

    1. 模型需要继承自db.Model, 然后需要映射到表中的属性,必须写成db.Column的数据类型

    2. 数据类型

      * db.Integer 代表的是整型

      * db.String 代表的是varchar 需要指定最长长度

      * db.Text 代表的是 text

    3. 最后需要调用db.create_all 来将模型真正的创建到数据库中

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    import config
    app = Flask(__name__)
    app.config.from_object(config)
    db=SQLAlchemy(app)

    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)

    db.create_all()

    @app.route('/')
    def index():
        return 'index!'

    if __name__ == '__main__':

        app.run(debug=True)

     

    ### Flask-SQLAlchemy数据的增、删、改、查

    1. 增

    @app.route('/')
    def index():
        # 增加:
        article1=Article(title='aaa',content='bbb')
        db.session.add(article1)
        # 事务
        db.session.commit()
        return 'index!'

    2. 查

    @app.route('/')
    def index():
    # 查
    result=Article.query.filter(Article.title=='aaa').all()
    article1=result[0]
    print(article1.title)
    print(article1.content)
    return 'index!'

    3. 改

    @app.route('/')
    def index():
    # 改
    # 1. 先把你要更改的数据查找出来
    article1 = Article.query.filter(Article.title=='aaa').first()
    # 2. 把这条数据,你需要修改的地方进行修改
    article1.title='new title'
    # 3. 做事物的提交

    db.session.commit()
    return 'index!'

    4. 删

    @app.route('/')
    def index():
    # 删
    # 1. 把需要删除的数据查找出来
    article1=Article.query.filter(Article.content=='bbb').first()
    # 2. 把这条数据删除掉
    db.session.delete(article1)
    # 3. 做事务提交
    db.session.commit()
    return 'index!'

     

    Flask-SQLAlchemy 外键及其关系

     * backref 是定义反向引用通过User.articles 范文这个模型所写文章

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    import config

    app = Flask(__name__)
    app.config.from_object(config)
    db=SQLAlchemy(app)

    # 用户表
    # create table users(
    #     id int primary key auto_increment,
    #     username varchar(100) not null
    # )
    # 文章表
    # create table article (
    #     id int primary key auto_increment
    #     title varchar(100) not null,
    #     content text not null,
    #     author_id int,
    #     foreign key 'author_id' references 'users.id'
    # )

    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'))
    db.create_all()

    @app.route('/')
    def index():
        # # 想要添加一篇文章,因为文章必须依赖用户而存在,所以首先应该添加一个用户
        # user1= User(username='zhiliao')
        # db.session.add(user1)
        # db.session.commit()
        # article1 = Article(title='aaa',content='bbb',author_id=3)
        # db.session.add(article1)
        # db.session.commit()

        # 我要找文章标题为aaa的这个作者
        # artile=Article.query.filter(Article.title=='aaa').first()
        # author_id=artile.author_id
        # user=User.query.filter(User.id==author_id).first()
        # print(user.username)

        # article = Article(title='aaa',content='bbb')
        # article.author = User.query.filter(User.id==3).first()
        # db.session.add(article)
        # db.session.commit()

        # 找文章标题为aaa的作者
        # artile= Article.query.filter(Article.title=='aaa').first()
        # print(artile.author.username)

        # 我要找到zhiliao这个用户的所有文章
        user = User.query.filter(User.username=='zhiliao').first()
        result=user.articles
        for article1 in result:
            print('-'*10)
            print(article1.title)
        return 'index!'

    if __name__ == '__main__':

        app.run(debug=True)

     

    多对多关系

    * 需要通过一个中间表进行关联

    * 中间表,不能通过`class`的方式实现,只能通过`db.Table`实现

    需要使用一个关键字参数 secondary=中间表来进行关联

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    import config

    app = Flask(__name__)
    app.config.from_object(config)
    db=SQLAlchemy(app)

    # create table article()(
    #     id int primary key auto_increment,
    #     title varchar(100)
    # )
    # create table tag(
    #     id int primary key auto_increment,
    #     name varchar(50) not null,
    # )
    # create table article_tag(
    #     article_id int,
    #     tag_id int,
    #     primary key(article_id,tag_id),
    #     foreign key `article_id`  references `article.id`
    #     foreign `key tag`_id references `tag.id`
    # )
    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)
                         )

    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)

    db.create_all()

    @app.route('/')
    def index():
        # article1=Article(title='aaa')
        # article2 = Article(title='bbb')
        # tag1 = Tag(name='111')
        # tag2 = Tag(name='222')
        # 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=='aaa').first()
        tags=article1.tags
        for tag in tags:
            print(tag.name)
        return 'index!'

    if __name__ == '__main__':

        app.run(debug=True)

     

    ### 分开models以及解决循环引用

    1. 分开models的目的:为了让代码更加方便的管理

    2. 如果解决循环引用:把db放在一个单独的文件中,切断循环引用

    exts.py

    from flask_sqlalchemy import SQLAlchemy
    db=SQLAlchemy()

    models.py

    from exts import db
    class Article(db.Model):
        __tablename__='article'
        id=db.Column(db.Integer,primary_key=True,autoincrement=True)

        title=db.Column(db.String(100),nullable=False)

    Flaskstu5.py

    from flask import Flask
    import config
    from models import Article
    from exts import db

    app = Flask(__name__)
    app.config.from_object(config)
    db.init_app(app)

    #把app推到app栈顶上了
    with app.app_context():
        db.create_all()

    @app.route('/')
    def index():
        return 'index!'
    if __name__ == '__main__':

        app.run(debug=True)

     

     

    ### Flask-Migrate的介绍与安装:

    1. 介绍: 因为采用 db.create_all 在后期修改字段的时候,不会自动的映射到数据库中,必须删除表,然后重新运行db.create_all 才会重新映射,这样不符合我们的需求,因此flask-migrate就是为了解决这个问题,它可以在每次修改模型后,可以将修改的东西映射到数据库中

     

     

    Cookie和session

    Cookie 在网站中 http请求是无状态的,也就是说即使第一次和服务器连接并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户

    Cookie,第一次登录后服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个,cookie存储的数据量有限,一般不超过4kb。

     

    Cookie和session区别 cookie是存储在本地浏览器,而session存储于服务器,存储在服务器的数据更加安全,不容易被窃取,但存储在服务器也有一定的弊端,就是会占用资源

     

    使用session的好处

    * 敏感数据不是直接发送回给浏览器,而是发送回一个session_id 服务器将session_id 和敏感数据做一个映射存储在session中,更加安全

    * session 可以设置过期时间,也从另外一方面,保证了用户账号安全

     

    用户登录成功,把用户的信息经过加密后存放到session中,并且产生一个唯一的session_id,再存入cookie返回给本地,下一次再访问的时候cookie数据自动的携带给服务器,服务器

    去除cookie中的session_id,然后找到session,去除其中数据并解密

     

    ###  flask中的session工作机制

    1. Flask中的session机制是:把敏感数据经过加密后放入session中,然后再把session存放到cookie中 ,下次请求的时候, 再从浏览器发送过来的cookie中读取session, 然后再从session中读取数据,进行解密,获取最终的用户数据

    2. Flask的这种session机制,可以节省生服务器的开销,因为吧所有的信息都存储到了客户端(浏览器)

    3. 安全是相对的,把session放到cookie中,经过加密,也是比较安全的

     

     

     

    ### 操作session

    1. Session 的操作方式

    * 使用session需要从flask中导入session,以后所有和session相关的操作都是这个变量来的

    * 使用session需要设置secret_key,用来做为加密用,并且这个secret_key 如果每次服务器启动后都变化的话,那么之前’session’ 就不能在通过当前这个secret_key进行解密了

    * 操作session 的时候,跟操作字典一样

    * 设置session的过期时间

    from flask import Flask,session
    import os
    from datetime import timedelta

    app = Flask(__name__)
    app.config['SECRET_KEY'] = os.urandom(24)
    # 默认31天过期,此时指定7天后过期
    app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)

    # 添加数据到session中
    # 操作session的时候,跟操作字典是一样的
    # secret_key
    @app.route('/')
    def index():
        session['username']='zhiliao'
        # 如果没有指定session的过期时间,那么默认是浏览器关闭后就自动结束

        # 如果设置了session的permanent属性为True,那么过期时间是31天
        session.permanent = True
        return 'index!'

    @app.route('/get/')

    def get():
        # session['username']
        # session.get('username')
        return session.get('username')

    @app.route('/delete/')
    def delete():
        print(session.get('username'))
        session.pop('username')
        print(session.get('username'))
        return 'success'

    @app.route('/clear/')

    def clear():
        print(session.get('username'))
        # 删除session中的所有数据
        session.clear()
        print(session.get('username'))
        return 'success'

    if __name__ == '__main__':

        app.run(debug=True)

     

    ###  get请求和post请求

    1. get请求:

    * 使用场景:如果只对服务器获取数据,并没有对服务器产生任何影响,那么这时候使用get请求

    * 传参:get请求传参是放在url中,并且是通过?的形式来制定key和value的

     

    2. post请求:

    * 使用场景:如果要对服务器产生影响,那么要使用post请求

    * 传参:post请求传参不是放在url中,是通过form data的形式发送给服务器的

     

     

    ### get和post请求获取参数

    1. get请求是通过 request.args 来获取

    2. Post请求是通过 request.form 来获取

    from flask import Flask,render_template,request
    app = Flask(__name__)
    @app.route('/')
    def index():
        return render_template('index.html')
    @app.route('/search/')
    def search():
        # print(request.args)
        q=request.args.get('q')
        return '用户提交的查询参数是: %s' %q
    # 默认的视图函数,只能采用get请求
    # 如果你想采用post请求,那么要写明
    @app.route('/login/',methods=['GET','POST'])
    def login():
        if request.method == 'GET':
            return render_template('login.html')
        else:
            username=request.form.get('username')
            password=request.form.get('password')
            print(username)
            print(password)
            return 'post'
    if __name__ == '__main__':

        app.run(debug=True)

    Login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <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>
    </body>
    </html>

    Search.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <a href="{{ url_for('search',q='hello') }}">跳转到搜索页面</a>
    </body>
    </html>

    ### g:global

    1. g对象是专门用来保存用户的数据的

    2. g对象再一次请求中的所有的代码的地方,都是可以使用的

     

    ### 钩子函数

    from flask import Flask,g,render_template,request
    from utils import  login_log
    app = Flask(__name__)
    @app.route('/')
    def index():
        return 'index'
    @app.route('/login/',methods=['GET','POST'])

    def login():
        if request.method == 'GET':
            return render_template('login.html')
        else:
            username=request.form.get('username')
            password=request.form.get('password')
            if username == 'zhiliao' and password == '123':
                # 就认为当前这个用户的用户名和密码正确
                g.username=username
                g.ip = 'xx'
                login_log()

                return '恭喜登录成功'
            else:

                return '您的用户名或密码错误'
    if __name__ == '__main__':

        app.run(debug=True)

    Utils.py

    from flask import g
    def login_log():
        print('当前登录用户是:%s' %g.username)

    def login_ip_log(ip):
        pass

    ### 钩子函数 (hook):

    1. Before_request

    * 在请求之前执行的

    *  是在视图函数执行之前执行的

    from flask import Flask, render_template, request,session,redirect,url_for,g
    import os
    app = Flask(__name__)
    app.config['SECRET_KEY']=os.urandom(24)
    @app.route('/')
    def index():
        print('index')
        return 'index'
    @app.route('/login/',methods=['GET','POST'])

    def login():
        print('login')
        if request.method == 'GET':
            return render_template('login.html')
        else:
            username=request.form.get('username')
            password=request.form.get('password')
            if username == 'zhiliao' and password == '123':
                # 就认为当前这个用户的用户名和密码正确
                session['username'] = username
                return '恭喜登录成功'
            else:

                return '您的用户名或密码错误'
    @app.route('/edit/')

    def edit():
        if hasattr(g,'username'):
            return '修改成功'
        else:

            return redirect(url_for('login'))

    # before_request: 在请求之前执行
    # before_request是在视图函数执行之前执行的
    # before_request这个函数只是一个装饰器,它可以把需要设置为钩子函数的代码放到视图函数执行之前来执行
    @app.before_request
    def my_before_request():
        if session.get('username'):
            g.username=session.get('username')
    if __name__ == '__main__':
        app.run(debug=True)

     

    2. Context_processor

    *上下文处理器应该返回一个字典,字典中的key会被模板中当成变量来渲染

    *上下文处理器中返回的字典,在所有页面中都是可用的

    @app.context_processor
    def my_context_processor():
        return {'username':'zhiliao'}

     

  • 相关阅读:
    转-iOS开发系列--地图与定位
    转-关于UIView的autoresizingMask属性的研究
    UIAlertController的使用,代替UIAlertView和UIActionSheet
    设置当前导航栏(navigationController)的标题
    tabBar隐藏方式
    ubuntu 安装qq 及解决安装完搜狗输入法不显示键盘的方法
    python 读写文件
    Ubuntu:如何显示系统托盘图标(systray)
    python tesseract 识别图片中的文字的乱码问题(ubuntu系统下)
    让Ubuntu可以压缩/解压缩RAR文件
  • 原文地址:https://www.cnblogs.com/JimKing/p/8615173.html
Copyright © 2011-2022 走看看